//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow
{
    #region Using directives.
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Security.Permissions;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Threading;
    using System.Workflow.ComponentModel.Compiler;
    using Microsoft.Practices.Unity;
    using Microsoft.Research.DataLayer;
    using Microsoft.Research.ScientificWorkflow.TridentComposer;
    using Microsoft.Research.ScientificWorkflow.TridentModel;
    using Microsoft.Research.ScientificWorkflow.TridentUtilities;
    using Microsoft.Research.ScientificWorkflow.TridentUtilities.Properties;
    using Microsoft.Research.ScientificWorkflow.UIDesigner;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.ActivityImportWizards;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.Commands;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.Import;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.Monitor;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.WpfComposite;
    using Microsoft.Win32;
    using Provenance;
    using TridentAPI;
    using SR = Microsoft.Research.DataLayer;
    #endregion

    /// <summary>
    /// Interaction logic for TridentWindow.xaml
    /// </summary>
    public sealed partial class TridentWindow : Window, IWorkflowExecution, IRegionManager, IDisposable
    {
        #region Declaration

        /// <summary>
        /// This is used to access connection manager API.
        /// </summary>
        private SR.ConnectionManager connMgr;

        /// <summary>
        /// This is used to access registry connection.
        /// </summary>
        private SR.Connection registryConnection;

        /// <summary>
        /// This is used to access the UI Designer Class.
        /// </summary>
        private UIHelper uiHelper;

        /// <summary>
        /// The workflow name form the Dialog Box above is stored in this Variable.
        /// </summary>
        private string newWorkflowName = string.Empty;

        /// <summary>
        /// The workflow description from the Save Dialog Box is stored in this Variable.
        /// </summary>
        private string newWorkflowDescription;

        /// <summary>
        /// The workflow category from the Dialog box is stored in here.
        /// </summary>
        private Guid newWorkflowCategory;

        /// </summary>
        /// Hods the Workflow tree control 
        /// </summary>
        private WorkflowTree workflowtree;

        /// <summary>
        /// Activity tree.
        /// </summary>
        private ActivityTree activityTree;

        /// <summary>
        /// Holds if the user rejected save of the current workflow before creating the new workflow.
        /// </summary>
        private bool usrRejectSave;

        /// <summary>
        /// Field to store the current job id
        /// </summary>
        private Guid currentJobId = Guid.Empty;

        /// <summary>
        /// connection object for pooling thread
        /// </summary>
        private SR.Connection poolingConnection;

        /// <summary>
        /// set to true when the job is terminated by the user, false otherwise
        /// </summary>
        private bool terminatedByUser;

        /// <summary>
        /// Composer control.
        /// </summary>
        private ComposerControl designerComposerControl;

        /// <summary>
        /// Gets whether the workflow job is running
        /// </summary>
        private bool IsWorkflowJobRunning
        {
            get { return (this.currentJobId != Guid.Empty) ? true : false; }
        }

        /// <summary>
        /// The datatypes present.
        /// </summary>
        private Dictionary<String, DataTypeModel> dataTypes = new Dictionary<string, DataTypeModel>();

        /// <summary>
        /// Container.
        /// </summary>
        private IUnityContainer container;

        /// <summary>
        /// Module implementaion.
        /// </summary>
        private IModule module;

        /// <summary>
        /// MenuItem reference for  Registry-Save 
        /// </summary>
        private MenuItem saveRegistryMenu;

        /// <summary>
        /// MenuItem reference for  FileaSystem-Save 
        /// </summary>
        private MenuItem saveFileSystemMenu;

        /// <summary>
        /// Holds true if save As event handler- Invoked
        /// </summary>
        private bool saveAsInvoked;

        /// <summary>
        /// Holds true if the JobTermination MessageBox can be displayed.
        /// </summary>
        private bool promptForJobTermination = true;

        /// <summary>
        /// Files opened from disk.
        /// </summary>
        private Collection<FileReference> openedReferences = new Collection<FileReference>();

        /// <summary>
        /// A control that indicates that there is some work happening in the background.
        /// </summary>
        private WaitControl waitControl;

        #endregion

        #region constructor
        /// <summary>
        /// Constructor.
        /// </summary>
        [SecurityPermission(System.Security.Permissions.SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
        public TridentWindow()
        {
            this.InitializeComponent();
            //App.Current.MainWindow = this;
            System.Windows.Forms.Application.EnableVisualStyles();
            System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
            this.Dispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(OnTridentWindowUnhandledException);
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
        }

        /// <summary>
        /// Initialize composer control.
        /// </summary>
        private void InitializeComposerControl()
        {
            this.designerComposerControl = new ComposerControl(this.registryConnection,
                this.uiHelper.WorkflowComposer,
                this.dataTypes,
                RenderMode.ComposerMode);
            this.designerComposerControl.Name = "designerComposerControl";
            this.RegisterName(this.designerComposerControl.Name, this.designerComposerControl);
            this.uiHelper.CurrentComposerControl = this.designerComposerControl;
            this.designerComposerControl.OnExecute += new EventHandler<ExecuteEventArgs>(this.OnWorkflowExecute);
            this.designerComposerControl.OnCloseWorkflow += new EventHandler(this.CloseWorkFlow_Click);
            this.tabItemComposer.Content = this.designerComposerControl;
        }

        /// <summary>
        /// Read the console parameters passed as command line parameter.
        /// </summary>
        private void ReadConsoleParameters()
        {
            try
            {
                if (Application.Current.Properties.Contains("workflowId"))
                {
                    string workflowToOpen = (string)Application.Current.Properties["workflowId"];
                    Guid workflowGuid = new Guid(workflowToOpen);
                    this.LoadWorkFlow(workflowGuid);
                }
                if (Application.Current.Properties.Contains("newWorkflow"))
                {
                    this.NewButton_Click(null, null);
                }
            }
            catch (FormatException)
            {
                TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("InvalidIdPassed"));
            }
            catch (OverflowException)
            {
                TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("InvalidIdPassed"));
            }
        }
        #endregion

        #region Event Handlers

        /// <summary>
        /// Event handler for Activity Mouse down
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">MouseButtonEventArgs</param>
        private void OnActivityMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ButtonState == MouseButtonState.Pressed)
            {
                try
                {
                    // Check if the Workflow designer is loaded in the Window
                    if (this.designerComposerControl.WorkflowSpaceGrid.Children.Count != 0)
                    {
                        this.StartDrag((System.Windows.DependencyObject)e.Source, ((HeaderedItemsControl)e.Source).DataContext);
                    }
                }
                catch (WorkflowValidationFailedException validationException)
                {
                    StringBuilder errorString = new StringBuilder();
                    foreach (System.Workflow.ComponentModel.Compiler.ValidationError error in validationException.Errors)
                    {
                        errorString.AppendLine(error.ErrorText);
                    }

                    TridentMessageBox.ShowTridentErrorMessageBox(this, errorString.ToString());
                }
                catch (TridentCustomException tridentException)
                {
                    TridentErrorHandler.HandleTridentCustomExceptionInUI(this, tridentException);
                }
                catch (Exception exception)
                {
                    TridentErrorHandler.HandleKnownExceptionsInUI(this, exception);
                }
            }
        }

        /// <summary>
        /// Event handler for WF tree Keyboard Enter Key Down Event
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">KeyboardEventArgs</param>
        private void OnWorkFlowEnterDown(object sender, KeyboardEventArgs e)
        {
            WorkflowMetadata selectedWorkFlow = ((HeaderedItemsControl)e.Source).DataContext as WorkflowMetadata;
            this.OpenWorkflowFromLeftPane(selectedWorkFlow);
        }

        /// <summary>
        /// Event handler for WF tree Mouse Double Click Event
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">MouseEventArgs</param>
        private void OnWorkFlowMouseDoubleClick(object sender, MouseEventArgs e)
        {
            WorkflowMetadata selectedWorkFlow = ((HeaderedItemsControl)e.Source).DataContext as WorkflowMetadata;
            this.OpenWorkflowFromLeftPane(selectedWorkFlow);
        }

        /// <summary>
        /// Event handler for New workflow click.
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">RoutedEventArgs</param>
        private void NewButton_Click(object sender, RoutedEventArgs e)
        {
            if (true == this.SaveChangedWorkflow())
            {
                return;
            }

            this.ShowComposerTab();
            try
            {
                this.designerComposerControl.RemovePropertyPaneOnChange();
                this.uiHelper.ClearOpenFromFileSystemDetails();
                this.designerComposerControl.ClearUICache();
                this.EnableDesignerTab();
                this.designerComposerControl.ResetTransforms();

                // Create a new SequentialWorkflow and render's to UI.
                this.uiHelper.CreateNewWorkflowActivity();

                this.uiHelper.CurrentStatus = WorkflowStatus.NewWorkflow.ToString();
                uiHelper.IsWFCommitted = true;

                //// clear the status text
                lblStatus.Text = string.Empty;

                // show execute button
                this.EnablePlayButton();

                // Refresh the activity tree.
                this.RefreshActivityTree(false);

                // Clear the Value of the Job Name.
                this.ClearConditionDataStore();
                this.EnableDisableSaveFileSystemMenu(true);
                this.EnableDisableSaveRegistryMenu(true);
                this.designerComposerControl.InitializeMachineCombo();

                this.openedReferences.Clear();
                // Uncheck the HideParameterBindings toggel button.
                this.tBtnHideParameterBindings.IsChecked = false;
            }
            catch (TridentCustomException tridentException)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(this, tridentException);
            }
            catch (Exception exp)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(this, exp);
            }

            // Set the title of the window.
            this.Title = this.SetTitle();
        }

        /// <summary>
        /// Event handler for close Workflow
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CloseWorkFlow_Click(object sender, EventArgs e)
        {
            if (true == this.SaveChangedWorkflow())
            {
                return;
            }

            this.DisableComposer();
        }

        /// <summary>
        /// Fired on click of the import button. Imports the workflow into the system.
        /// </summary>
        /// <param name="sender">
        /// Import button.
        /// </param>
        /// <param name="e">
        /// RoutedEventArgs.
        /// </param>
        private void OnImportClick(object sender, RoutedEventArgs e)
        {
            if (this.SaveChangedWorkflow())
            {
                return;
            }

            this.uiHelper.ImportWorkflow(this.registryConnection);
        }

        /// <summary>
        /// Fired on click of the import button. Imports an activities into the system.
        /// </summary>
        /// <param name="sender">
        /// Import button.
        /// </param>
        /// <param name="e">
        /// RoutedEventArgs.
        /// </param>
        private void OnImportActivityClick(object sender, RoutedEventArgs e)
        {
            this.uiHelper.ImportActivities();
        }

        /// <summary>
        /// This function used to add the wait control to the parent grid during the import activity process.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnRemoveWaitControl(object sender, EventArgs e)
        {
            // Get the top-most grid of the main window.
            Grid parentGrid = Application.Current.MainWindow.Content as Grid;
            if (parentGrid != null)
            {
                // Enable all child elements.
                foreach (UIElement element in parentGrid.Children)
                {
                    element.IsEnabled = true;
                }

                // Add the wait control.
                parentGrid.Children.Remove(this.waitControl);
            }
            this.Cursor = Cursors.Arrow;
        }

        /// <summary>
        /// This function used to remove the wait control after the import of activity completes.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAddWaitControl(object sender, WaitMessageEventArgs e)
        {
            this.Cursor = Cursors.Wait;

            // Get the top-most grid of the main window.
            Grid parentGrid = Application.Current.MainWindow.Content as Grid;
            if (parentGrid != null)
            {
                // Create an instance of the wait control.
                if (this.waitControl == null)
                {
                    this.waitControl = new WaitControl(e.WaitMessage);
                    Grid.SetRowSpan(this.waitControl, 3);
                }
                // Disable all existing children in this grid.
                foreach (UIElement element in parentGrid.Children)
                {
                    element.IsEnabled = false;
                }

                // Add the wait control.
                parentGrid.Children.Add(this.waitControl);
            }
            else
            {
                // If parent grid cannot be retrieved, add a wait cursor.
                Application.Current.MainWindow.Cursor = Cursors.Wait;
            }
        }

        /// <summary>
        /// Fired when user selects Import Custom Type option.
        /// </summary>
        /// <param name="sender">
        /// Import Custom Type menu item.
        /// </param>
        /// <param name="e">
        /// Attributes of the event.
        /// </param>
        private void OnImportCustomType(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openDialog = new OpenFileDialog();

            // Filters the type dll in the current Directory.
            openDialog.Filter = "Custom type initializer assemblies |*.dll; *.exe";

            // Checks and promts the user if the file is not present in the directory.
            openDialog.CheckFileExists = true;

            // Check if File Exists in directory Specified.
            openDialog.CheckPathExists = true;

            // Restores the previous Directory the user had selected to Open/Save the file.
            openDialog.RestoreDirectory = true;

            // Window title.
            openDialog.Title = TridentResourceManager.GetString("ImportTypeInitializer");

            if ((bool)openDialog.ShowDialog())
            {
                this.uiHelper.ImportCustomTypes(openDialog.FileName);
            }
        }

        /// <summary>
        /// Called when import web service activity click.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OnImportWebServiceActivityClick(object sender, RoutedEventArgs e)
        {
            ActivityWizard activityWizard =
                new ActivityWizard(ActivityWizardType.WebService, this.registryConnection);
            activityWizard.Owner = Application.Current.MainWindow;
            activityWizard.ShowInTaskbar = false;
            activityWizard.ShowDialog();

            // Refresh ActivityTree for newly added activities.
            this.RefreshActivityTree(true);

            // If subsection activity was imported, initialize subsection metadata.
            if (SubsectionMetadata.Data == null)
            {
                this.InitializeSubSectionMetadata();
            }
        }

        /// <summary>
        /// Called when import workflow package is clicked.
        /// </summary>
        /// <param name="sender">
        /// Import Workflow Package menu item.
        /// </param>
        /// <param name="e">
        /// Attributes of the event.
        /// </param>
        private void OnImportWorkflowPackage(object sender, RoutedEventArgs e)
        {
            if (this.SaveChangedWorkflow())
            {
                return;
            }

            this.uiHelper.ImportWorkflowPackage();
        }

        /// <summary>
        /// Fired on click of the open button.
        /// </summary>
        /// <param name="sender">
        /// Open button.
        /// </param>
        /// <param name="e">
        /// RoutedEventArgs.
        /// </param>
        private void OpenButton_Click(object sender, RoutedEventArgs e)
        {
            this.ShowComposerTab();
            if (this.SaveChangedWorkflow())
            {
                return;
            }

            try
            {
                this.Cursor = Cursors.Wait;

                this.ClearConditionDataStore();

                this.designerComposerControl.RemovePropertyPaneOnChange();


                bool? openStatus = this.uiHelper.OpenWorkflowFromFileSystem(this.openedReferences);
                if (openStatus.HasValue && this.openedReferences != null)
                {
                    if (!openStatus.Value)
                    {
                        TridentMessageBox.ShowTridentErrorMessageBox("Open of the workflow failed.");
                        this.designerComposerControl.RefreshUI();
                    }
                    else
                    {
                        // Set the Filename of the file Selected.
                        FileReference workflowFile = this.openedReferences.SingleOrDefault(F => Helper.IsWorkflowFile(F.FilePath));
                        if (workflowFile != null)
                        {
                            uiHelper.OpenedFileName = System.IO.Path.GetFileNameWithoutExtension(workflowFile.FilePath);
                            uiHelper.OpenedFileLocation = System.IO.Path.GetDirectoryName(workflowFile.FilePath);

                            // Set the values which is used to decide whether the workflow is commited to Registry.
                            uiHelper.CurrentStatus = WorkflowStatus.OpenedFromFileSystem.ToString();
                            uiHelper.IsWFCommitted = true;

                            //// clear the status text
                            lblStatus.Text = string.Empty;

                            //// show execute button
                            this.EnablePlayButton();
                            this.EnableDesignerTab();
                            this.designerComposerControl.ResetTransforms();

                            this.ShowComposerTab();

                            // Clear the Value of the Job Name.
                            this.designerComposerControl.TxtJobName.ClearText();

                            this.tBtnHideParameterBindings.IsChecked = false;
                            this.designerComposerControl.InitializeMachineCombo();
                        }
                    }
                }

                this.EnableDisableSaveFileSystemMenu(true);
                this.EnableDisableSaveRegistryMenu(false);

            }
            catch (WorkflowValidationFailedException validationException)
            {
                StringBuilder errorString = new StringBuilder();
                errorString.AppendLine(TridentResourceManager.GetString("ErrorXOMLValidationError1"));
                errorString.AppendLine(TridentResourceManager.GetString("ErrorXOMLValidationError2"));
                foreach (System.Workflow.ComponentModel.Compiler.ValidationError error in validationException.Errors)
                {
                    errorString.AppendLine(error.ErrorText);
                }

                TridentMessageBox.ShowTridentErrorMessageBox(this, errorString.ToString());
                this.designerComposerControl.RefreshUI();
                this.uiHelper.ApplyBackup();
            }
            catch (TridentCustomException exception)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(this, exception);
                this.designerComposerControl.RefreshUI();
                this.uiHelper.ApplyBackup();
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(this, exception);
                this.uiHelper.ApplyBackup();
            }
            finally
            {
                if (!this.uiHelper.IsWorkflowOpen)
                {
                    this.DisableDesignerTab();
                }

                this.Cursor = Cursors.Arrow;
            }

            // Set the title of the window.
            this.Title = this.SetTitle();
        }

        /// <summary>
        /// This is handled essentially for preventing app crashes and doing appropriate logging.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">DispatcherUnhandledExceptionEventArgs</param>
        private void OnTridentWindowUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            TridentErrorHandler.HandleKnownExceptionsInUI(this, e.Exception);
            if (e.Exception != null && (e.Exception is BackendStorageException || e.Exception.InnerException is BackendStorageException))
            {
                e.Handled = true;
            }
        }

        /// <summary>
        /// This is handled essentially for preventing app crashes and doing appropriate logging.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">UnhandledExceptionEventArgs</param>
        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            TridentErrorHandler.HandleKnownExceptionsInUI(this, (Exception)e.ExceptionObject);
        }

        /// <summary>
        /// Event handler for the save workflow to registry click.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event arguments</param>
        private void SaveAsWorkflowReg_Click(object sender, RoutedEventArgs e)
        {
            //// Check if any workflow is open.
            if (this.uiHelper.CurrentStatus == WorkflowStatus.WorkflowClosed.ToString())
            {
                TridentMessageBox.ShowTridentErrorMessageBox(
                    this,
                    TridentResourceManager.GetString("SaveWorkflowNoOpenWorkflow"));

                return;
            }

            // store the workflow id - If any exception occurs, It will be rolled back to old Id
            Guid savedWorkflowId = Guid.Empty;
            try
            {
                this.Cursor = Cursors.Wait;

                if (this.uiHelper != null && this.uiHelper.ComposerWorkflowModel != null)
                {
                    savedWorkflowId = this.uiHelper.ComposerWorkflowModel.Id;
                }

                this.saveAsInvoked = true;
                this.designerComposerControl.RemovePropertyPaneOnChange();
                this.SaveWorkflowToRegistry();
                if (!this.usrRejectSave)
                {
                    this.ClearConditionDataStore();

                    // Reload the saved Workflow
                    this.uiHelper.LoadWorkflowFromLeftPane(this.uiHelper.ComposerWorkflowModel.Id);

                    this.ChangeSaveButtonState(!this.designerComposerControl.CurrentWorkflowModel.NewerVersionsExist);

                    this.SetTitle();

                    this.EnablePlayButton();
                }
            }
            catch (WorkflowValidationFailedException validationException)
            {
                StringBuilder errorString = new StringBuilder();
                foreach (System.Workflow.ComponentModel.Compiler.ValidationError error in validationException.Errors)
                {
                    errorString.AppendLine(error.ErrorText);
                }
                this.uiHelper.ComposerWorkflowModel.Id = savedWorkflowId;
                TridentMessageBox.ShowTridentErrorMessageBox(this, errorString.ToString());
            }
            catch (TridentCustomException tridentCustomException)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(this, tridentCustomException);
                this.uiHelper.ComposerWorkflowModel.Id = savedWorkflowId;
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(this, exception, TridentResourceManager.GetString("SaveWorkflowFailedToSavedIntoRegistry"));
                this.uiHelper.ComposerWorkflowModel.Id = savedWorkflowId;
            }
            finally
            {
                this.Cursor = Cursors.Arrow;
                this.saveAsInvoked = false;
                if (!this.usrRejectSave)
                {
                    this.uiHelper.ClearOpenFromFileSystemDetails();
                }
            }
        }

        /// <summary>
        /// Handles the Click event of the SaveWorkflowReg control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void SaveWorkflowReg_Click(object sender, RoutedEventArgs e)
        {
            // Check if any workflow is open.
            if (this.uiHelper.CurrentStatus == WorkflowStatus.WorkflowClosed.ToString())
            {
                TridentMessageBox.ShowTridentErrorMessageBox(
                    this,
                    TridentResourceManager.GetString("SaveWorkflowNoOpenWorkflow"));

                return;
            }

            try
            {
                this.Cursor = Cursors.Wait;
                this.designerComposerControl.RemovePropertyPaneOnChange();
                this.SaveWorkflowToRegistry();
            }
            catch (WorkflowValidationFailedException validationException)
            {
                StringBuilder errorString = new StringBuilder();
                foreach (System.Workflow.ComponentModel.Compiler.ValidationError error in validationException.Errors)
                {
                    errorString.AppendLine(error.ErrorText);
                }

                TridentMessageBox.ShowTridentErrorMessageBox(this, errorString.ToString());
            }
            catch (TridentCustomException tridentCustomException)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(this, tridentCustomException);
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(this, exception, TridentResourceManager.GetString("SaveWorkflowFailedToSavedIntoRegistry"));
            }
            finally
            {
                this.Cursor = Cursors.Arrow;
            }

        }

        /// <summary>
        /// Event handler for Save As File System
        /// </summary>
        /// <param name="sender">saveasFile MenuItem</param>
        /// <param name="e">RoutedEventArgs</param>
        private void SaveAsWorkflowFile_Click(object sender, RoutedEventArgs e)
        {
            this.SaveWorkflowFile_Click(sender, e);
        }

        /// <summary>
        /// Event handler for Save As WFL File.
        /// </summary>
        /// <param name="sender">saveasWflFile MenuItem</param>
        /// <param name="e">RoutedEventArgs</param>
        private void SaveAsWFLFile_Click(object sender, RoutedEventArgs e)
        {
            bool validSave = true;
            if (this.uiHelper.CurrentStatus == WorkflowStatus.WorkflowClosed.ToString())
            {
                TridentMessageBox.ShowTridentErrorMessageBox(
                    this,
                    TridentResourceManager.GetString("SaveWorkflowNoOpenWorkflow"));
                validSave = false;
            }

            if (validSave && this.uiHelper.CurrentWorkflowId.Equals(Guid.Empty))
            {
                TridentMessageBox.ShowTridentErrorMessageBox(
                    this,
                    TridentResourceManager.GetString("SaveOfNonRegistryWfAsWfl"));
                validSave = false;
            }

            if (validSave)
            {
                try
                {
                    Activity wfToSave = Activity.Load(this.uiHelper.CurrentWorkflowId, this.registryConnection);
                    if (null == wfToSave || wfToSave.IsDeleted)
                    {
                        TridentMessageBox.ShowTridentErrorMessageBox(
                            this,
                            TridentResourceManager.GetString("SaveAsWflDeleted"));
                        validSave = false;
                    }
                }
                catch (Exception ex)
                {
                    TridentErrorHandler.HandleUIException(ex);
                }
            }

            if (validSave && this.uiHelper.CurrentStatus.ToString().Equals(WorkflowStatus.OpenedFromRegistry.ToString()) && !this.uiHelper.WorkflowComposer.CheckWorkflowAuthorAccess(this.uiHelper.ComposerWorkflowModel.Id))
            {
                // If the logged in user does not have author permission
                TridentMessageBox.ShowTridentErrorMessageBox(
                    this,
                    TridentCommonResourceManager.GetString("WorkflowPermissionDenied"));
                this.DisableComposer();
                this.RefreshWorkFlowTree();
                validSave = false;
            }

            if (validSave && WflFileHelper.SaveAsWfl(this.uiHelper.CurrentWorkflowId))
            {
                lblStatus.Text = TridentResourceManager.GetString("WflSavedToFileSystem");
            }
        }

        /// <summary>
        /// Event handler for the save workflow to file click.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event arguments</param>
        private void SaveWorkflowFile_Click(object sender, RoutedEventArgs e)
        {
            if (this.uiHelper.CurrentStatus == WorkflowStatus.WorkflowClosed.ToString())
            {
                TridentMessageBox.ShowTridentErrorMessageBox(
                    this,
                    TridentResourceManager.GetString("SaveWorkflowNoOpenWorkflow"));
                return;
            }

            Collection<AssemblyInfoModel> multiAsmModels = new Collection<AssemblyInfoModel>();
            bool validSave = this.CheckSaveValidity(out multiAsmModels);
            if (!validSave)
            {
                StringBuilder multiActivities = new StringBuilder();
                foreach (AssemblyInfoModel model in multiAsmModels)
                {
                    multiActivities.AppendLine(model.HolderModel.Label);
                }

                TridentMessageBox.ShowTridentErrorMessageBox(
                    this,
                    string.Format(CultureInfo.InvariantCulture, TridentResourceManager.GetString("InvalidSaveVersionProblem"), multiActivities.ToString()));
                return;
            }

            if (this.uiHelper.CurrentStatus.ToString().Equals(WorkflowStatus.OpenedFromRegistry.ToString()) && !this.uiHelper.WorkflowComposer.CheckWorkflowAuthorAccess(this.uiHelper.ComposerWorkflowModel.Id))
            {
                // If the logged in user does not have author permission
                TridentMessageBox.ShowTridentErrorMessageBox(
                    this,
                    TridentCommonResourceManager.GetString("WorkflowPermissionDenied"));
                this.DisableComposer();
                this.RefreshWorkFlowTree();
                return;
            }

            try
            {
                this.Cursor = Cursors.Wait;
                this.SaveWorkflowToFileSystem();
                this.designerComposerControl.RemovePropertyPaneOnChange();
            }
            catch (TridentCustomException tridentCustomException)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(this, tridentCustomException);
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(this, exception);
            }
            finally
            {
                this.Cursor = Cursors.Arrow;
            }
        }

        /// <summary>
        /// This event is raised when the default save is clicked.
        /// </summary>
        /// <param name="sender">Default save button.</param>
        /// <param name="e">RoutedEventArgs</param>
        private void SaveWorkflowClick(object sender, RoutedEventArgs e)
        {
            if (this.uiHelper.CurrentStatus.Equals(WorkflowStatus.OpenedFromFileSystem.ToString()))
            {
                this.SaveWorkflowFile_Click(sender, e);
            }
            else
            {
                this.SaveWorkflowReg_Click(sender, e);
            }

            this.ShowComposerTab();
        }

        /// <summary>
        /// Event handler for the trident window closing.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event arguments</param>
        private void tridentWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // Ask for saving the wf.
            if (this.SaveChangedWorkflow())
            {
                e.Cancel = true;
            }

            if (!e.Cancel && this.IsWorkflowJobRunning)
            {
                MessageBoxResult result = TridentMessageBox.ShowTridentConfirmationYesNoCancelMessageBox(ScientificWorkFlow.CloseRunningWorkFlowConfirmation);
                if (result == MessageBoxResult.Yes)
                {
                    this.uiHelper.AbortCurrentJob(this.currentJobId);
                }
                else if (result == MessageBoxResult.No)
                {
                    //Do not abort the job
                }
                else if (result == MessageBoxResult.Cancel)
                {
                    e.Cancel = true;
                }
            }

            if (!e.Cancel)
            {
                // serialize the datatype xml.
                UIHelper.SaveUserDataTypeXml(this.dataTypes);
                try
                {
                    this.container.Resolve<IMonitorService>().HaltService();
                }
                catch (Exception)
                {
                }

                try
                {
                    this.container.Resolve<IDataProductService>().HaltService();
                }
                catch (Exception)
                {
                }
            }
        }

        /// <summary>
        /// Event handler for the trident window load.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event arguments</param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Set the Title of App.
            this.Title = this.SetTitle();
            this.InitializeRegistry();
            this.InitializeConnection();
            this.InitializeUI();
        }

        /// <summary>
        /// This event is raised when the execute button is clicked. 
        /// </summary>
        /// <param name="sender">Execute button.</param>
        /// <param name="e">ExecuteEventArgs</param>
        private void OnWorkflowExecute(object sender, ExecuteEventArgs e)
        {
            Dictionary<ParameterDescriptionModel, object> originalValueDictionary = null;
            bool runWindowCancelClicked = false;
            this.ShowMonitorTab();
            this.ShowComposerTab();

            if (this.uiHelper.CurrentStatus == WorkflowStatus.WorkflowClosed.ToString())
            {
                TridentMessageBox.ShowTridentErrorMessageBox(
                    this,
                    TridentResourceManager.GetString("ExecuteNoWorkflowLoaded"));

                return;
            }

            try
            {
                // Check if the workflow has been deleted from some other source.
                if (!this.uiHelper.ComposerWorkflowModel.Id.Equals(Guid.Empty) &&
                    this.uiHelper.WorkflowComposer.CheckIfWorkflowDeleted(this.uiHelper.ComposerWorkflowModel.Id))
                {
                    TridentMessageBox.ShowTridentErrorMessageBox(this,
                        TridentResourceManager.GetString("DeletedWorkflowExecute"));
                    uiHelper.IsWFCommitted = true;
                    this.DisableComposer();
                    this.RefreshWorkFlowTree();
                    return;
                }

                if (!this.SaveWorkFlowBeforeExecute())
                {
                    return;
                }

                object nodeToExecuteOn = e.SelectedMachine;
                if (this.designerComposerControl != null)
                {
                    if (this.designerComposerControl.SelectedNode != null)
                    {
                        nodeToExecuteOn = this.designerComposerControl.SelectedNode;
                    }

                    if (!this.IsNodeSelectedValid(nodeToExecuteOn))
                    {

                        this.designerComposerControl.InitializeMachineCombo();
                        return;
                    }
                }

                // To check whether previous job execution is completed or not.
                // If not completed then prompt user and get his confirmation 
                //      to stop the previous monitoring of previous job.
                if (!this.CanProceedOnJobExecution())
                {
                    return;
                }

                this.Cursor = Cursors.Wait;

                // Get the JobName form the UI.
                string jobName = string.Empty;
                if (false == string.IsNullOrEmpty(e.JobName))
                {
                    jobName = e.JobName.Trim();
                }

                // clear the data prodcuts before executing new job
                this.ClearDataProducts();

                Machine machine = nodeToExecuteOn as Machine;

                // Create a jobdetail model. This contains enough data to create a job.
                JobDetailModel jobDetails = new JobDetailModel();
                jobDetails.JobName = jobName;
                jobDetails.IsTemplate = false;
                jobDetails.WorkflowId = this.designerComposerControl.CurrentWorkflowModel.Id;
                jobDetails.WorkflowName = this.designerComposerControl.CurrentWorkflowModel.Name;

                // Check if the workflow required parameters are entered. Else bring up the run window.
                runWindowCancelClicked = !this.GetWorkflowRequiredParameters(jobDetails, out originalValueDictionary);
                if (runWindowCancelClicked)
                {
                    // If user has clicked cancel in the run window then return.
                    return;
                }

                jobDetails.ParameterInfo = this.designerComposerControl.CurrentWorkflowModel.CreateWorkflowParameterInfo();

                // Save the Job to registry.
                this.currentJobId = uiHelper.CreateWorkflowJob(jobDetails, (machine as IObject).ID, e.IsDebug);

                this.MonitorComposerControl.ConditionStore.ClearDataStore();

                this.ShowMonitorTab();

                // update the buttons to show execution state
                this.DisablePlayButton();
                this.MonitorComposerControl.EnableTerminateButton();

                this.terminatedByUser = false;

                try
                {
                    this.container.Resolve<IDataProductService>().StartDataProductService(this.currentJobId, this.poolingConnection);
                    this.container.Resolve<IMonitorService>().Start(this.currentJobId);
                }
                catch (ResolutionFailedException)
                {
                }

                // Execute attached commands.
                JobCommands.ExecuteCommand.Execute(null);

            }
            catch (TridentCustomException tridentException)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(this, tridentException);
                if (tridentException.ErrorNumber.Equals(TridentErrorConstants.ErrorNumber1000000069.ToString(CultureInfo.InvariantCulture)))
                {
                    uiHelper.IsWFCommitted = true;
                    this.DisableComposer();
                    this.RefreshWorkFlowTree();
                    return;
                }
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(this, exception);
            }
            finally
            {
                // Revert the changes done in the run window.
                if (!runWindowCancelClicked && originalValueDictionary != null)
                {
                    foreach (ParameterDescriptionModel key in originalValueDictionary.Keys)
                    {
                        key.Value = originalValueDictionary[key];
                    }
                }
                this.Cursor = Cursors.Arrow;
            }

            // Set the title of the window.
            this.Title = this.SetTitle();
        }

        /// <summary>
        /// Determines whether [is node selected valid] [the specified machine obj].
        /// </summary>
        /// <param name="machineObj">The machine obj.</param>
        /// <returns>
        /// 	<c>true</c> if [is node selected valid] [the specified machine obj]; otherwise, <c>false</c>.
        /// </returns>
        private bool IsNodeSelectedValid(object machineObj)
        {
            bool isValid = false;
            try
            {
                if (machineObj.ToString().Equals(TridentUtilities.Properties.ScientificWorkFlow.SelectNodeText))
                {
                    TridentMessageBox.ShowTridentErrorMessageBox(TridentUtilities.Properties.ScientificWorkFlow.SelectNodeWarning);
                    return false;
                }

                Machine machine = machineObj as Machine;
                if (machine != null)
                {
                    Machine reloadedMachine = Machine.Load((machineObj as IObject).ID, this.registryConnection);
                    if (!reloadedMachine.IsDeleted && reloadedMachine.Availability == ExecutorAvailabiltiy.Online)
                    {
                        isValid = true;
                    }
                    else
                    {
                        TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("InvalidNodeSelectedToExecuteJob"));
                    }
                }
                else
                {
                    TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("InvalidNodeSelectedToExecuteJob"));
                }
            }
            catch (RecordNotFoundException ex)
            {
                TridentErrorHandler.HandleUIException(ex);
                TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("InvalidNodeSelectedToExecuteJob"));
            }
            return isValid;
        }

        /// <summary>
        /// Event handler for Activity Expander Expanded
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">RoutedEventArgs</param>
        private void ActivityExpander_Expanded(object sender, RoutedEventArgs e)
        {
            this.activityExpander.Tag = TridentResourceManager.GetString("TridentWindowTreeCollapseToolTip");
        }

        /// <summary>
        /// Event handler for Activity Expander Collapsed
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">RoutedEventArgs</param>
        private void ActivityExpander_Collapsed(object sender, RoutedEventArgs e)
        {
            this.activityExpander.Tag = TridentResourceManager.GetString("TridentWindowTreeExpandToolTip");
        }

        /// <summary>
        /// Event handler for Workflow Expander Expanded
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">RoutedEventArgs</param>
        private void WorkflowExpander_Expanded(object sender, RoutedEventArgs e)
        {
            // Set the Minimum and Maximum height for the Workflow tree inorder to get the Scroll viewer while expanding
            this.workflowExpander.MinHeight = 300;
            this.workflowExpander.MaxHeight = 300;

            workflowExpander.Tag = TridentResourceManager.GetString("TridentWindowTreeCollapseToolTip");
        }

        /// <summary>
        /// Event handler for Workflow Expander Collapsed
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">RoutedEventArgs</param>
        private void WorkflowExpander_Collapsed(object sender, RoutedEventArgs e)
        {
            // Set the Minimum and Maximum height for the Workflow tree as 30, Inorder to Move the Activity Tree up
            this.workflowExpander.MinHeight = 30;
            this.workflowExpander.MaxHeight = 30;
            this.workflowExpander.Tag = TridentResourceManager.GetString("TridentWindowTreeExpandToolTip");
        }

        /// <summary>
        /// Open Lite connection Manager Dialogue.
        /// </summary>
        /// <param name="sender">
        /// Connection button.
        /// </param>
        /// <param name="e">
        /// RoutedEventArgs.
        /// </param>
        private void OnSavedConnection(object sender, RoutedEventArgs e)
        {
            this.ShowConnectionManager(ConnectionManagerBase.UIStyleType.Lite);
        }

        /// <summary>
        /// Open Advance connection Manager Dialogue.
        /// </summary>
        /// <param name="sender">
        /// Connection button.
        /// </param>
        /// <param name="e">
        /// RoutedEventArgs.
        /// </param>
        private void OnAdvancedConnection(object sender, RoutedEventArgs e)
        {
            this.ShowConnectionManager(ConnectionManagerBase.UIStyleType.Normal);
        }

        /// <summary>
        /// Updates the job status in the status bar
        /// </summary>
        /// <param name="sender">background thread</param>
        /// <param name="e">job status</param>
        private void OnUpdateJobStatus(object sender, JobStatusEventArgs e)
        {
            try
            {
                //// updating the status text for all the states
                string formatString = (e.Status == JobStatus.Completed || e.Status == JobStatus.Aborted) ? "{0} {1}." : "{0} {1}. . .";
                lblStatus.Text = string.Format(CultureInfo.CurrentUICulture, formatString, e.JobName, e.Status.ToString());

                if (e.Status == JobStatus.Waiting &&
                    !string.IsNullOrEmpty(e.ErrorMessage) &&
                    e.ErrorMessage.Equals(ScientificWorkFlow.JobTerminatedByUserMessage, StringComparison.OrdinalIgnoreCase) && promptForJobTermination)
                {
                    promptForJobTermination = false;

                    MessageBoxResult confirmResult =
                        TridentMessageBox.ShowTridentConfirmationYesNoMessageBox(
                        ScientificWorkFlow.JobRetryMessage);

                    if (confirmResult == MessageBoxResult.No)
                    {
                        MessageBoxResult finalConfirmResult =
                            TridentMessageBox.ShowTridentConfirmationYesNoMessageBox(
                            ScientificWorkFlow.JobTerminateConfirmMessage);

                        if (finalConfirmResult == MessageBoxResult.Yes)
                        {
                            this.terminatedByUser = true;
                            this.uiHelper.AbortCurrentJob(this.currentJobId);
                            this.container.Resolve<IMonitorService>().HaltService();
                        }
                    }
                    promptForJobTermination = true;
                }

                //// need to retain the status text so moved first, otherwise EnablePlayButton() will clear the message
                if (e.Status == JobStatus.Completed || e.Status == JobStatus.Aborted)
                {
                    // Load provenance if workflow is completed or Aborted.
                    this.LoadProvenanceView();

                    this.currentJobId = Guid.Empty;
                    this.EnablePlayButton();
                }

                if (e.Status == JobStatus.StopPending)
                {
                    this.MonitorComposerControl.DisableTerminateButton();
                }

                if (e.Status == JobStatus.Aborted)
                {
                    if (this.terminatedByUser)
                    {
                        lblStatus.Text = string.Format(CultureInfo.CurrentUICulture,
                            formatString,
                            e.JobName,
                            ScientificWorkFlow.JobTerminatedByUserMessage);
                    }
                    else
                    {
                        //// in the case of job termination by the execution service prompt the error and clear the status message
                        TridentMessageBox.ShowTridentErrorMessageBox(
                            string.Format(CultureInfo.CurrentUICulture,
                            ScientificWorkFlow.UIHelperProblemExecuting,
                            e.ErrorMessage));
                        lblStatus.Text = string.Empty;
                    }
                }
            }
            catch (Exception ex)
            {
                TridentErrorHandler.HandleUIException(ex);
            }
        }

        /// <summary>
        /// This is the event handler for hide/show parameter bindings.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HideParameterBindings_Click(object sender, RoutedEventArgs e)
        {
            if (true == this.tBtnHideParameterBindings.IsChecked)
            {
                // Hide all Parameter Bindings in workflow.
                this.designerComposerControl.ToggleAllParameterBindings(Visibility.Collapsed);
            }
            else
            {
                // Show all parameter Bindings in workflow.
                this.designerComposerControl.ToggleAllParameterBindings(Visibility.Visible);
            }
        }

        /// <summary>
        /// Fired on selection change of the tab control.
        /// </summary>
        /// <param name="sender">
        /// TabControl.
        /// </param>
        /// <param name="e">
        /// SelectionChangedEventArgs.
        /// </param>
        private void OnTabSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.OriginalSource.Equals(sender))
            {
                WindowCollection childWindows = this.OwnedWindows;
                foreach (Window child in childWindows)
                {
                    if (child.Tag != null && child.Tag.ToString().StartsWith("DataTypesLegendCtrl", StringComparison.OrdinalIgnoreCase))
                    {
                        child.Hide();
                    }
                }

                if (this.ComposerTab.SelectedIndex == 0 && this.uiHelper != null && this.uiHelper.IsWorkflowOpen)
                {
                    // Enable the Toggle button which is used to hide the Parameter bindings.
                    this.tBtnHideParameterBindings.IsEnabled = true;
                }
                else
                {
                    // Diable the Toggle button which is used to hide the Parameter bindings.
                    this.tBtnHideParameterBindings.IsEnabled = false;
                }
            }
        }
        #endregion

        #region Private Methods

        /// <summary>
        /// Enables the Play Button and sets its opacity as 1
        /// </summary>
        private void EnablePlayButton()
        {
            // Enable the Play Button.
            this.designerComposerControl.EnablePlayButton();

            this.MonitorComposerControl.EnablePlayButton();

            this.saveButton.IsEnabled = true;

            if (this.ComposerTab.SelectedIndex == 0)
            {
                // Diable the Toggle button which is used to hide the Parameter bindings.
                this.tBtnHideParameterBindings.IsEnabled = true;
            }

            this.monitorSettingsButton.IsEnabled = true;
        }

        /// <summary>
        /// Enables the Play Button and sets its opacity as 1
        /// </summary>
        private void DisablePlayButton()
        {
            this.designerComposerControl.DisablePlayButton();
            this.MonitorComposerControl.DisablePlayButton();
            this.monitorSettingsButton.IsEnabled = false;
        }

        /// <summary>
        /// This function is used to open the workflow from the left pane.
        /// </summary>
        /// <param name="selectedWorkFlow"></param>
        private void OpenWorkflowFromLeftPane(WorkflowMetadata selectedWorkFlow)
        {
            if (selectedWorkFlow != null)
            {

                try
                {
                    // Check if the workflow being loaded is deleted by an external source.
                    if (this.uiHelper.WorkflowComposer.CheckIfWorkflowDeleted(selectedWorkFlow.Id))
                    {
                        TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("DeletedWorkflowOpen"));

                        // Disable the composer if the selected workflow is opened in the Composer
                        if (uiHelper.CurrentWorkflowId.Equals(selectedWorkFlow.Id))
                        {
                            this.DisableComposer();
                        }

                        this.RefreshWorkFlowTree();
                        return;
                    }

                    bool sameWorkflowSelected = this.designerComposerControl != null &&
                        this.designerComposerControl.CurrentWorkflowModel != null &&
                        this.designerComposerControl.CurrentWorkflowModel.Id.Equals(selectedWorkFlow.Id);

                    // Save the changes in the workflow.
                    if (this.SaveChangedWorkflow())
                    {
                        return;
                    }

                    this.designerComposerControl.ResetTransforms();
                    this.EnableDesignerTab();
                    this.ClearConditionDataStore();
                    this.designerComposerControl.RemovePropertyPaneOnChange();

                    this.LoadWorkFlow(sameWorkflowSelected ? this.designerComposerControl.CurrentWorkflowModel.Id : selectedWorkFlow.Id);
                    this.ShowComposerTab();
                    this.openedReferences.Clear();
                }
                catch (TridentCustomException tridentException)
                {
                    TridentErrorHandler.HandleTridentCustomExceptionInUI(this, tridentException);
                    if (tridentException.ErrorNumber.Equals(TridentErrorConstants.ErrorNumber1000000069.ToString(CultureInfo.InvariantCulture)))
                    {
                        uiHelper.IsWFCommitted = true;
                        this.DisableComposer();
                        this.RefreshWorkFlowTree();
                        return;
                    }
                }
                catch (Exception exception)
                {
                    TridentErrorHandler.HandleKnownExceptionsInUI(this, exception, TridentResourceManager.GetString("OnWorkFlowLoadFailed"));
                }
            }
        }

        /// <summary>
        /// Get the values for the empty workflow required parameters from the user. If all values are entered then dont
        /// bring up the run window.
        /// </summary>
        /// <param name="job">The job details.</param>
        /// <param name="originalValueDictionary">Dictionary containing the actual parameter values.</param>
        /// <returns>True if OK has been clicked. False if Cancel is clicked</returns>
        private bool GetWorkflowRequiredParameters(JobDetailModel job, out Dictionary<ParameterDescriptionModel, Object> originalValueDictionary)
        {
            bool result = true;
            Collection<ParameterDescriptionModel> workflowRequiredParameters =
                this.designerComposerControl.CurrentWorkflowModel.GetWorkflowRequiredParameters();

            originalValueDictionary = null;

            ParameterDescriptionModel nullValueModel =
                workflowRequiredParameters.FirstOrDefault(p => p.Value == null || (!p.IsDatabound &&
                !PropertyListControl.ValidateInputValue(p.Value.ToString(), p, ValidationMode.All)));

            // If some value is null in the workflow required parameter models then show a window with the property list.
            if (nullValueModel != null)
            {
                // Make a dictionary of the old values. 
                // The new values entered in the Run window needs to be reset once the job is created.
                originalValueDictionary = new Dictionary<ParameterDescriptionModel, object>();
                foreach (ParameterDescriptionModel model in workflowRequiredParameters)
                {
                    originalValueDictionary.Add(model, model.Value);
                }

                RunWindow runWindow = new RunWindow(
                    workflowRequiredParameters,
                    this.designerComposerControl.CurrentWorkflowModel.GetWorkflowOutputParameters(),
                    job);
                runWindow.Owner = Application.Current.MainWindow;
                runWindow.ShowDialog();
                result = !runWindow.CancelClicked;
            }
            return result;
        }

        /// <summary>
        /// Loads provenance view.
        /// </summary>
        private void LoadProvenanceView()
        {
            if (this.currentJobId != Guid.Empty)
            {
                try
                {
                    ProvenanceControl provenanceControl = new ProvenanceControl(this.registryConnection, this.currentJobId, this.dataTypes);

                    provenanceControl.VerticalAlignment = VerticalAlignment.Top;

                    if (this.ProvenanceDisplayRegion.Children.Count > 0)
                    {
                        this.ProvenanceDisplayRegion.Children.Clear();
                    }

                    this.ProvenanceDisplayRegion.Children.Add(provenanceControl);
                }
                catch (Exception ex)
                {
                    TridentErrorHandler.HandleUIException(ex);
                }
            }
        }

        /// <summary>
        /// Initializes the UI.
        /// </summary>
        private void InitializeUI()
        {
            try
            {
                this.InitializeUIHelper();
                this.ReadDatatypes();
                this.InitializeComposerControl();
                this.InitializeMonitorControl();

                this.uiHelper.CurrentStatus = WorkflowStatus.WorkflowClosed.ToString();

                try
                {
                    DataProductIconBuilder.Initialize();
                    DataProductIconBuilder.ExtractIcons();
                }
                catch (TridentCustomException ex)
                {
                    TridentErrorHandler.HandleUIException(ex);
                }

                this.InitializeContainer();
                this.InitializeModules();
                this.container.Resolve<IDataProductService>().UpdateStatus += OnUpdateJobStatus;

                // Load the details in the Left Pane.
                this.LoadLeftPane();

                this.InitializeSubSectionMetadata();

                this.GetSaveMenuItems();

                // Load default workflow if specified in command line.
                this.ReadConsoleParameters();
            }
            catch (TridentCustomException tridentException)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(this, tridentException);
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(this, exception, TridentResourceManager.GetString("Trident_LoaderError"));
            }
        }

        #region Registry Connection

        /// <summary>
        /// Shows the connection manager dialog.
        /// </summary>
        /// <param name="styleType">
        /// Dialog type.
        /// </param>
        private void ShowConnectionManager(ConnectionManagerBase.UIStyleType styleType)
        {
            this.connMgr.UIStyle = styleType;
            bool saveFailed = false;
            try
            {
                saveFailed = this.SaveChangedWorkflow();
            }
            catch (TridentCustomException customExp)
            {
                TridentErrorHandler.HandleUIException(customExp);
                TridentMessageBox.ShowTridentErrorMessageBox(customExp.Message);
            }
            catch (Exception ex)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(ex);
            }

            try
            {
                if (!saveFailed || !this.registryConnection.Alive)
                {
                    if (this.ReInitializeConnection())
                    {
                        // Refresh UI.
                        this.RefreshUIComposer();
                    }
                }
            }
            catch (TridentCustomException customExp)
            {
                TridentErrorHandler.HandleUIException(customExp);
                TridentMessageBox.ShowTridentErrorMessageBox(customExp.Message);
            }
            catch (Exception ex)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(ex);
            }
        }

        /// <summary>
        ///  Initialize Connection.
        /// </summary>
        private void InitializeConnection()
        {
            bool isValid;

            SR.BackendStorageException connFailure;
            if (connMgr.HasDefaultConnection && !connMgr.TestConnection(connMgr.DefaultConnection, out connFailure))
            {
                TridentMessageBox.ShowTridentErrorMessageBox(connFailure.InnerException.Message);
                isValid = false;
            }
            else
            {
                isValid = true;
            }

            do
            {
                try
                {
                    if (!isValid)
                    {
                        registryConnection = connMgr.PickConnection(SR.ConnectionManager.ConnectionUI.AlwaysShowUI);
                    }
                    else
                    {
                        registryConnection = connMgr.PickConnection(SR.ConnectionManager.ConnectionUI.PromptIfNeeded);
                    }

                    if (null != registryConnection)
                    {
                        if (!Helper.IsValidConnection(registryConnection))
                        {
                            TridentMessageBox.ShowTridentErrorMessageBox(
                                TridentCommonResourceManager.GetString("InvalidRegistryConnection"));
                            isValid = false;
                            continue;
                        }

                        registryConnection.AutoSave = false;

                        this.AuthenticateUser();

                        TypeProviderHelper.Initialize(this.registryConnection);
                        ExternalRegistryHelperProxy.Initialize(this.registryConnection);

                        this.poolingConnection = this.registryConnection.Clone();
                        this.poolingConnection.Open();
                    }

                    isValid = true;
                }
                catch (SR.ConnectionFailure connectionFailure)
                {
                    TridentErrorHandler.HandleUIException(connectionFailure);
                    TridentMessageBox.ShowTridentErrorMessageBox(connectionFailure.InnerException.Message);
                    isValid = false;
                }
                catch (InvalidOperationException exception)
                {
                    TridentErrorHandler.HandleUIException(exception);
                    TridentMessageBox.ShowTridentErrorMessageBox(exception.Message);
                    isValid = false;
                }
                catch (TridentCustomException customExp)
                {
                    TridentErrorHandler.HandleTridentCustomExceptionInUI(customExp, false);
                    isValid = false;
                }
                catch (Exception exception)
                {
                    TridentErrorHandler.HandleKnownExceptionsInUI(exception, false);
                    isValid = false;
                }
            } while (!isValid);

            if (null == registryConnection)
            {
                TridentMessageBox.ShowTridentErrorMessageBox(
                    TridentCommonResourceManager.GetString("RegistryNotSelected"));
                Environment.Exit(0);
            }
        }

        /// <summary>
        /// Initializes the registry.
        /// </summary>
        private void InitializeRegistry()
        {
            try
            {
                // Initialize Connection.
                SR.SR_Connection.Init();
                connMgr = SR.ConnectionManager.Create(SR.ConnectionManager.CancelBehavior.ThrowException);
                connMgr.UIStyle = ConnectionManagerBase.UIStyleType.Lite;
            }
            catch (Microsoft.Research.DataLayer.ConnectionFailure connectionFailure)
            {
                TridentErrorHandler.HandleUIException(connectionFailure);
                TridentMessageBox.ShowTridentErrorMessageBox(connectionFailure.InnerException.Message);
                Environment.Exit(0);
            }
            catch (InvalidOperationException exception)
            {
                TridentErrorHandler.HandleUIException(exception);
                TridentMessageBox.ShowTridentErrorMessageBox(exception.Message);
                Environment.Exit(0);
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(exception);
                Environment.Exit(0);
            }
        }

        /// <summary>
        /// ReInitialize connection.
        /// </summary>
        /// <returns>
        /// True if Connection successfully created, False otherwise.
        /// </returns>
        private bool ReInitializeConnection()
        {
            bool isValid;
            bool connectionChanged = false;
            do
            {
                try
                {
                    Connection conn = connMgr.PickConnection(SR.ConnectionManager.ConnectionUI.AlwaysShowUI);
                    if (conn != null && conn.Alive)
                    {
                        if (!Helper.IsValidConnection(conn))
                        {
                            TridentMessageBox.ShowTridentErrorMessageBox(
                                TridentCommonResourceManager.GetString("InvalidRegistryConnection"));
                            isValid = false;
                            continue;
                        }

                        connectionChanged = true;
                        this.registryConnection = conn;

                        // Disable AutoSave.
                        registryConnection.AutoSave = false;

                        // Check whether user exist or not if not then create new user in registry.
                        CategoriesComposer.CreateUser(TridentAuthentication.LoggedUserInUserName, registryConnection);

                        // Authenticate user in the new connection.
                        this.AuthenticateUser();

                        // Resets the system policy.
                        SystemPolicy.Reset();

                        // Re intialise Pooling Connection
                        this.poolingConnection = this.registryConnection.Clone();
                        this.poolingConnection.Open();

                        TypeProviderHelper.Initialize(this.registryConnection);
                        ExternalRegistryHelperProxy.Initialize(this.registryConnection);
                    }

                    isValid = true;
                }
                catch (SR.ConnectionFailure connectionFailure)
                {
                    TridentErrorHandler.HandleUIException(connectionFailure);
                    TridentMessageBox.ShowTridentErrorMessageBox(connectionFailure.InnerException.Message);
                    isValid = false;
                }
                catch (TridentCustomException customExp)
                {
                    TridentErrorHandler.HandleTridentCustomExceptionInUI(customExp, false);
                    isValid = false;
                }
                catch (Exception ex)
                {
                    TridentErrorHandler.HandleKnownExceptionsInUI(ex, false);
                    isValid = false;
                }
            } while (!isValid);

            return connectionChanged;
        }

        /// <summary>
        /// Authenticates the user.
        /// </summary>
        private void AuthenticateUser()
        {
            TridentAuthentication authendicate = new TridentAuthentication(this.registryConnection);
            authendicate.AuthenticateUser();

            // If the user is guest, then dont allow him to access the application
            if (TridentAuthentication.LoggedUserRole == UserRole.Guest)
            {
                TridentErrorHandler.ThrowTridentCustomException(
                    TridentErrorConstants.ErrorNumber1000000072,
                    TridentAuthentication.INVALIDLOGINERROR);
            }
        }

        #endregion

        /// <summary>
        ///  Initialize Ui Helper.
        /// </summary>
        private void InitializeUIHelper()
        {
            try
            {
                uiHelper = new UIHelper(registryConnection);

                // add the event handlers.
                uiHelper.ActivityImported += new EventHandler<ImportEventArgs>(this.OnActivityImported);
                uiHelper.WorkflowPackageImported += new EventHandler<ImportEventArgs>(this.OnWorkflowPackageImported);
                uiHelper.WorkflowImported += new EventHandler<ImportEventArgs>(this.OnWorkflowImported);
                uiHelper.CustomTypeImported += new EventHandler<ImportEventArgs>(this.OnCustomTypeImported);

                // add handlers for the wait control functionality for import.
                this.uiHelper.AddWaitControl += new EventHandler<WaitMessageEventArgs>(this.OnAddWaitControl);
                this.uiHelper.RemoveWaitControl += new EventHandler<EventArgs>(this.OnRemoveWaitControl);

                // Set the Default state for the Composer
                uiHelper.CurrentStatus = WorkflowStatus.WorkflowClosed.ToString();
            }
            catch (TridentCustomException tridentException)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(this, tridentException);
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(this, exception);
            }
        }

        /// <summary>
        /// This event is fired to retrieve the status of the import process for custom type.
        /// </summary>
        /// <param name="sender">sender object</param>
        /// <param name="e">event arguments</param>
        private void OnCustomTypeImported(object sender, ImportEventArgs e)
        {
            bool result = e.Status;
            // on failure of import function.
            if (!result)
            {
                if (!string.IsNullOrEmpty(e.ErrorMessage))
                {
                    TridentMessageBox.ShowTridentErrorMessageBox(this, e.ErrorMessage);
                }
            }
            else
            {
                this.openedReferences.Clear();
                lblStatus.Text = TridentResourceManager.GetString("ImportCustomTypeInitializersSuccess");
            }
        }

        /// <summary>
        /// This event is fired to retrieve the status of the import process for workflow.
        /// </summary>
        /// <param name="sender">sender object</param>
        /// <param name="e">event arguments</param>
        private void OnWorkflowImported(object sender, ImportEventArgs e)
        {
            bool result = e.Status;
            // on failure of import function.
            if (!result)
            {
                if (!string.IsNullOrEmpty(e.ErrorMessage))
                {
                    TridentMessageBox.ShowTridentErrorMessageBox(this,
                            string.Concat(TridentResourceManager.GetString("WorkflowImportFail"), Environment.NewLine, e.ErrorMessage));
                }
            }
            else
            {
                this.openedReferences.Clear();
                lblStatus.Text = TridentResourceManager.GetString("ImportWorkflowSuccess");
                RefreshWorkFlowTree();
                RefreshActivityTree(true);

                // If subsection activity was imported, initialize subsection metadata.
                if (SubsectionMetadata.Data == null)
                {
                    this.InitializeSubSectionMetadata();
                }
            }
        }

        /// <summary>
        /// This event is fired to retrieve the status of the import process for workflow package.
        /// </summary>
        /// <param name="sender">sender object</param>
        /// <param name="e">event arguments</param>
        private void OnWorkflowPackageImported(object sender, ImportEventArgs e)
        {
            bool result = e.Status;
            string message = TridentResourceManager.GetString("ImportPackageFailed");

            // on failure of import function.
            if (!result)
            {
                // Get the error string and append it to the generic message.
                if (!string.IsNullOrEmpty(e.ErrorMessage))
                    message += e.ErrorMessage;
                TridentMessageBox.ShowTridentErrorMessageBox(this, message);
            }
            else
            {
                this.openedReferences.Clear();
                lblStatus.Text = TridentResourceManager.GetString("WorkflowPackageImported");
                RefreshWorkFlowTree();
                RefreshActivityTree(true);

                // If subsection activity was imported, initialize subsection metadata.
                if (SubsectionMetadata.Data == null)
                {
                    this.InitializeSubSectionMetadata();
                }
            }
        }

        /// <summary>
        /// This event is fired to retrieve the status of the import process for activity.
        /// </summary>
        /// <param name="sender">sender object</param>
        /// <param name="e">event arguments</param>
        private void OnActivityImported(object sender, ImportEventArgs e)
        {
            bool result = e.Status;

            // on failure of import function.
            if (!result)
            {
                if (!string.IsNullOrEmpty(e.ErrorMessage))
                {
                    TridentMessageBox.ShowTridentErrorMessageBox(
                        string.Concat(TridentResourceManager.GetString("ActivityImportFail"), Environment.NewLine, e.ErrorMessage));
                }
            }
            else
            {
                this.openedReferences.Clear();
                lblStatus.Text = TridentResourceManager.GetString("ImportActivitiesSuccess");
                RefreshActivityTree(true);

                // If subsection activity was imported, initialize subsection metadata.
                if (SubsectionMetadata.Data == null)
                {
                    this.InitializeSubSectionMetadata();
                }
            }
        }

        #region Left pane
        /// <summary>
        /// Loads the Left pane
        /// </summary>
        private void LoadLeftPane()
        {
            try
            {
                this.LoadActivityTree();
                this.LoadWorkFlowTree();
            }
            catch (TridentCustomException ex)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(Application.Current.MainWindow, ex);
            }
            catch (Exception ex)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(Application.Current.MainWindow, ex);
            }
        }

        /// <summary>
        /// Loads the Workflow in the Left pane
        /// </summary>
        private void LoadWorkFlowTree()
        {
            Collection<WorkflowCategoryModel> categoryList = uiHelper.FetchWorkflowCategories();
            if (null != categoryList)
            {
                if (TridentAuthentication.LoggedUserRole == UserRole.NormalUser)
                {
                    WorkflowCategoryModel sharedCategory = WorkflowCategoryModel.CreateSharedWorkflows(this.registryConnection);
                    if (sharedCategory != null &&
                        (sharedCategory.Categories.Count > 0 || sharedCategory.Workflows.Count > 0))
                    {
                        categoryList.Add(sharedCategory);
                    }
                }

                if (TridentAuthentication.LoggedUserRole == UserRole.Admin)
                {
                    WorkflowCategoryModel allUserCategory = WorkflowCategoryModel.CreateVirtualAllUserCategory(this.registryConnection);
                    if (allUserCategory != null &&
                        (allUserCategory.Categories.Count > 0 || allUserCategory.Workflows.Count > 0))
                    {
                        categoryList.Add(allUserCategory);
                    }
                }

                this.workflowtree = new WorkflowTree(categoryList);
                workflowtree.OnWorkflowMouseDown += new MouseEventHandler(this.OnWorkFlowMouseDoubleClick);
                workflowtree.OnWorkflowEnterDown += new KeyboardEventHandler(this.OnWorkFlowEnterDown);
                workflowtree.OnWorkflowDelete += new EventHandler(this.OnWorkFlowDelete);
                workflowtree.OnWorkflowLabel += new EventHandler(this.OnWorkflowLabel);
                workflowtree.CreateWorkflowCategory += new EventHandler(this.OnCreateWorkflowCategory);
                this.grdWorkFlowTree.Children.Add(workflowtree);
            }
            this.SetWorkflowExpanderHeader();
        }

        /// <summary>
        /// Event handler to delete Workflow
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">EventArgs</param>
        private void OnWorkFlowDelete(object sender, EventArgs e)
        {
            try
            {
                TreeViewItem selectedItem = sender as TreeViewItem;
                if (selectedItem != null && selectedItem.DataContext != null)
                {
                    WorkflowMetadata workflow = selectedItem.DataContext as WorkflowMetadata;

                    // If the workflow has been deleted externally, refresh and return.
                    if (uiHelper.WorkflowComposer.CheckIfWorkflowDeleted(workflow.Id))
                    {
                        TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("DeletedWorkflowDelete"));

                        this.RefreshWorkFlowTree();

                        // Disable the composer if the selected workflow is opened in the Composer
                        if (uiHelper.CurrentWorkflowId.Equals(workflow.Id))
                        {
                            this.DisableComposer();
                        }
                        return;
                    }

                    // Show a confirmation message to the user.
                    MessageBoxResult result = TridentMessageBox.ShowTridentConfirmationYesNoMessageBox(ScientificWorkFlow.WorkFlowDeleteConfirmation);
                    if (result == MessageBoxResult.Yes)
                    {
                        if (workflow != null)
                        {
                            Activity workflowToDelete = Activity.Load(workflow.Id, this.registryConnection);

                            if (workflowToDelete != null)
                            {
                                WorkflowComposer.DeleteWorkflow(workflowToDelete);
                            }

                            this.RefreshWorkFlowTree();

                            // Disable the composer if the selected workflow is opened in the Composer
                            if (uiHelper.CurrentWorkflowId.Equals(workflow.Id))
                            {
                                this.DisableComposer();
                            }

                            lblStatus.Text = TridentResourceManager.GetString("DeleteWorkflowMsg");
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(this, exception);
            }
        }

        /// <summary>
        /// Retrieve the label for the workflow by popping up a dialog and save the label.
        /// </summary>
        /// <param name="sender">origin of the event.</param>
        /// <param name="e">Event args.</param>
        private void OnWorkflowLabel(object sender, EventArgs e)
        {
            try
            {
                TreeViewItem treeViewItem = sender as TreeViewItem;
                WorkflowMetadata metadata = treeViewItem.DataContext as WorkflowMetadata;
                LabelDialog labelDialog = new LabelDialog(metadata, this.uiHelper);
                labelDialog.Owner = this;
                labelDialog.ShowDialog();
                if (labelDialog.LabelWorkflowSuccess)
                {
                    WorkflowTree.ChangeDisplayName(treeViewItem, metadata);

                    // If the labelled version is currently open then change the model and the title.
                    if (this.uiHelper.CurrentWorkflowId.Equals(metadata.Id))
                    {
                        this.uiHelper.ComposerWorkflowModel.VersionLabel = metadata.VersionLabel;
                        this.Title = this.SetTitle();
                    }
                }
            }
            catch (TridentCustomException ex)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(this, ex);
            }
        }

        /// <summary>
        /// Creates a new workflow category.
        /// </summary>
        /// <param name="sender">
        /// Workflow tree control.
        /// </param>
        /// <param name="e">
        /// Attributes of the event.
        /// </param>
        private void OnCreateWorkflowCategory(object sender, EventArgs e)
        {
            try
            {
                TreeViewItem treeViewItem = sender as TreeViewItem;
                if (treeViewItem != null)
                {
                    WorkflowCategoryModel catModel = treeViewItem.DataContext as WorkflowCategoryModel;
                    if (catModel != null)
                    {
                        Namespace category = Namespace.Load(catModel.Id, this.registryConnection);
                        NamespaceDialog namespaceDialog = new NamespaceDialog(category, this.registryConnection);
                        namespaceDialog.Owner = this;
                        namespaceDialog.ShowDialog();

                        if (namespaceDialog.Namespace != null)
                        {
                            // Refresh the tree.
                            this.RefreshWorkFlowTree();
                        }
                    }
                }
            }
            catch (TridentCustomException ex)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(this, ex);
            }
        }

        /// <summary>
        /// Refreshes the Workflow
        /// </summary>
        private void RefreshWorkFlowTree()
        {
            try
            {
                // Refresh the system policy object to take care of any changes in the role of the user.
                Helper.RefreshSystemPolicy(this.registryConnection);

                Collection<WorkflowCategoryModel> activityList = uiHelper.FetchWorkflowCategories();
                if (null != activityList)
                {
                    if (TridentAuthentication.LoggedUserRole == UserRole.NormalUser)
                    {
                        WorkflowCategoryModel sharedCategory = WorkflowCategoryModel.CreateSharedWorkflows(this.registryConnection);
                        if (sharedCategory != null &&
                            (sharedCategory.Categories.Count > 0 || sharedCategory.Workflows.Count > 0))
                        {
                            activityList.Add(sharedCategory);
                        }
                    }
                    if (TridentAuthentication.LoggedUserRole == UserRole.Admin)
                    {
                        WorkflowCategoryModel allUserCategory = WorkflowCategoryModel.CreateVirtualAllUserCategory(this.registryConnection);
                        if (allUserCategory != null &&
                            (allUserCategory.Categories.Count > 0 || allUserCategory.Workflows.Count > 0))
                        {
                            activityList.Add(allUserCategory);
                        }
                    }

                    this.workflowtree.RefreshWorkflowTree(activityList);
                    this.grdWorkFlowTree.Children.Clear();
                    this.grdWorkFlowTree.Children.Add(workflowtree);
                }
            }
            catch (TridentCustomException ex)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(Application.Current.MainWindow, ex);
            }
            catch (Exception ex)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(ex);
            }
        }

        /// <summary>
        /// Loads activity tree from the Registry
        /// </summary>
        private void LoadActivityTree()
        {
            Collection<ActivityCategoryModel> categories = uiHelper.FetchActivityCategories();
            if (null != categories)
            {
                this.activityTree = new ActivityTree(categories, this.registryConnection);
                this.activityTree.OnActivityMouseDown += new MouseButtonEventHandler(this.OnActivityMouseDown);
                this.activityTree.CategoryExpanding += new EventHandler(OnCategoryExpanding);
                this.activityTree.ActivitiesLoaded += new EventHandler(OnActivitiesLoaded);
                this.grdActivityTree.Children.Add(this.activityTree);
                this.SetActivityExpanderHeader();
            }
        }

        /// <summary>
        /// Loads activity tree from the Registry
        /// </summary>
        private void RefreshActivityTree(bool refreshActivityVersionInfo)
        {
            Hashtable modelsHash = new Hashtable();
            Collection<BaseModel> oldModels = new Collection<BaseModel>();
            if (this.uiHelper.ComposerWorkflowModel != null)
            {
                modelsHash = this.uiHelper.ComposerWorkflowModel.ModelsHashtable;

                // Fetch a list of activities which are of older versions.
                foreach (BaseModel model in modelsHash.Values)
                {
                    if (refreshActivityVersionInfo && !model.Id.Equals(Guid.Empty))
                    {
                        this.RefreshVersionInfo(model);
                    }

                    if (!model.IsLatest)
                    {
                        oldModels.Add(model);
                    }
                }
            }

            try
            {
                Collection<ActivityCategoryModel> categories = uiHelper.FetchActivityCategories();
                if (categories != null)
                {
                    this.activityTree.RefreshTree(categories, oldModels);
                }
            }
            catch (TridentCustomException ex)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(Application.Current.MainWindow, ex);
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(Application.Current.MainWindow, exception);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public void RefreshVersionInfo(BaseModel activityModel)
        {
            try
            {
                // Check if an update is available.
                Activity latestActivity = BaseModel.CheckIfUpdateAvailable(Activity.Load(activityModel.Id, this.registryConnection));
                if (latestActivity != null)
                {
                    activityModel.UpdateAvailable = true;
                    activityModel.LatestEntityId = (latestActivity as IObject).ID;
                }
            }
            catch (TridentCustomException ex)
            {
                TridentErrorHandler.HandleUIException(ex);
            }
        }

        /// <summary>
        /// Loads the Workflow in the UI
        /// </summary>
        /// <param name="selectedWorkFlow">Activity</param>
        private void LoadWorkFlow(Guid selectedWorkFlowId)
        {
            this.ShowComposerTab();
            this.uiHelper.ClearOpenFromFileSystemDetails();
            if (this.uiHelper.LoadWorkflowFromLeftPane(selectedWorkFlowId))
            {
                if (this.designerComposerControl.WorkflowSpaceGrid.Children.Count != 0)
                {
                    this.uiHelper.CurrentStatus = WorkflowStatus.OpenedFromRegistry.ToString();
                    uiHelper.IsWFCommitted = true;
                    uiHelper.OpenedFileLocation = string.Empty;

                    //// clear the status text
                    lblStatus.Text = string.Empty;

                    this.EnablePlayButton();
                    this.tBtnHideParameterBindings.IsChecked = false;
                }
                else
                {
                    this.DisablePlayButton();
                    this.saveButton.IsEnabled = false;
                }

                this.Title = this.SetTitle();

                // Clear the Value of the Job Name.
                this.designerComposerControl.TxtJobName.ClearText();
                //  this.lastStoredFilePath = string.Empty;
                this.EnableDisableSaveFileSystemMenu(false);

                if (this.designerComposerControl.CurrentWorkflowModel.NewerVersionsExist)
                {
                    this.ChangeSaveButtonState(false);
                }
                else
                {
                    this.EnableDisableSaveRegistryMenu(true);
                }

                this.designerComposerControl.InitializeMachineCombo();
                this.RefreshActivityTree(false);
            }
        }

        /// <summary>
        /// Get the Menu for the save button using Template-FindName
        /// </summary>
        private void GetSaveMenuItems()
        {
            this.saveRegistryMenu = this.saveButton.Template.FindName("SaveRegistryMenuItem", this.saveButton) as MenuItem;
            this.saveFileSystemMenu = this.saveButton.Template.FindName("SaveFileSystemMenuItem", this.saveButton) as MenuItem;
        }

        /// <summary>
        /// Enables or disables the Registry Menu
        /// </summary>
        /// <param name="isenabled">bool</param>
        private void EnableDisableSaveRegistryMenu(bool isenabled)
        {
            this.saveRegistryMenu.IsEnabled = isenabled;
            if (isenabled)
            {
                this.saveRegistryMenu.Opacity = 1.0;
            }
            else
            {
                this.saveRegistryMenu.Opacity = 0.5;
            }
        }

        /// <summary>
        /// Enables or disables the File System Menu
        /// </summary>
        /// <param name="isenabled">bool</param>
        private void EnableDisableSaveFileSystemMenu(bool isenabled)
        {
            this.saveFileSystemMenu.IsEnabled = isenabled;
            if (isenabled)
            {
                this.saveFileSystemMenu.Opacity = 1.0;
            }
            else
            {
                this.saveFileSystemMenu.Opacity = 0.5;
            }
        }

        /// <summary>
        /// Change the state of the save button.
        /// </summary>
        /// <param name="isEnabled">The state.</param>
        private void ChangeSaveButtonState(bool isEnabled)
        {
            this.saveButton.IsEnabled = isEnabled;
        }

        /// <summary>
        /// Refresh the UI Composer
        /// </summary>
        private void RefreshUIComposer()
        {
            // Clear UI
            this.designerComposerControl.ClearUICache();

            this.grdWorkFlowTree.Children.Clear();
            this.grdActivityTree.Children.Clear();
            this.InitializeUIHelper();

            this.tabItemComposer.Content = this.designerComposerControl;
            this.UnregisterName(this.designerComposerControl.Name);
            this.InitializeComposerControl();
            this.DisableDesignerTab();
            this.LoadLeftPane();

            // Monitor refresh.
            this.MonitorRegion.Children.Clear();
            this.UnregisterName(this.MonitorComposerControl.Name);
            this.InitializeMonitorControl();

            // Clear data products region.
            this.ClearDataProducts();
            this.currentJobId = Guid.Empty;

            // Clear provenance display region.
            this.ProvenanceDisplayRegion.Children.Clear();

            this.InitializeSubSectionMetadata();

            this.container.RegisterInstance<ComposerControl>("Monitor", this.MonitorComposerControl, new ExternallyControlledLifetimeManager());
            this.container.RegisterInstance<UIHelper>("UiHelper", this.uiHelper, new ExternallyControlledLifetimeManager());

            lblStatus.Text = string.Empty;
        }
        #endregion

        /// <summary>
        /// Event handler for the start drag event on the activity.
        /// </summary>
        /// <param name="source">source of the drag</param>
        /// <param name="data">Drag data.</param>
        private void StartDrag(System.Windows.DependencyObject source, object data)
        {
            try
            {
                DragDrop.DoDragDrop(source, data, DragDropEffects.Copy);
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleUIException(exception);
                TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("DragWorkflowActivityNotSupported"));
            }
        }

        /// <summary>
        /// Saves the workflow to registry.
        /// </summary>
        private void SaveWorkflowToRegistry()
        {
            this.usrRejectSave = false;

            if (!this.designerComposerControl.SaveConditionalActivities())
            {
                this.usrRejectSave = true;
                return;
            }

            Collection<AssemblyInfoModel> multiAsmModels = new Collection<AssemblyInfoModel>();
            bool validSave = this.CheckSaveValidity(out multiAsmModels);
            if (!validSave)
            {
                StringBuilder multiActivities = new StringBuilder();
                foreach (AssemblyInfoModel model in multiAsmModels)
                {
                    multiActivities.AppendLine(model.HolderModel.Label);
                }

                TridentMessageBox.ShowTridentErrorMessageBox(
                    this,
                    string.Format(CultureInfo.InvariantCulture, TridentResourceManager.GetString("InvalidSaveVersionProblem"), multiActivities.ToString()));
                this.usrRejectSave = true;
                return;
            }

            // Check if the workflow being saved has been deleted by an external source.
            if (uiHelper.CurrentStatus == WorkflowStatus.OpenedFromRegistry.ToString())
            {
                if (this.uiHelper.WorkflowComposer.CheckIfWorkflowDeleted(this.uiHelper.ComposerWorkflowModel.Id))
                {
                    // If the workflow has been deleted.
                    TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("DeletedWorkflowSave"));
                    this.DisableComposer();
                    this.RefreshWorkFlowTree();
                    this.usrRejectSave = true;
                    return;
                }
                else if (!this.uiHelper.WorkflowComposer.CheckWorkflowAuthorAccess(this.uiHelper.ComposerWorkflowModel.Id))
                {
                    // If the logged in user does not have author permission
                    TridentMessageBox.ShowTridentErrorMessageBox(TridentCommonResourceManager.GetString("WorkflowPermissionDenied"));
                    this.DisableComposer();
                    this.RefreshWorkFlowTree();
                    this.usrRejectSave = true;
                    return;
                }
            }

            bool showImportDialog = this.uiHelper.CurrentStatus.Equals(WorkflowStatus.OpenedFromFileSystem.ToString(), StringComparison.Ordinal);
            if (this.EnsureInputsValid(this.uiHelper.ComposerWorkflowModel, true, showImportDialog))
            {
                if (uiHelper.CurrentStatus == WorkflowStatus.OpenedFromRegistry.ToString() && !saveAsInvoked)
                {
                    // Need to Commit the Changes to Registry.
                    uiHelper.UpdateWorkflow();
                }
                else
                {
                    this.newWorkflowName = this.uiHelper.ComposerWorkflowModel.Name;
                    this.newWorkflowDescription = this.uiHelper.ComposerWorkflowModel.Description;
                    this.newWorkflowCategory = this.uiHelper.ComposerWorkflowModel.Category.Id;

                    Collection<FileReference> references = new Collection<FileReference>();
                    if (uiHelper.CurrentStatus == WorkflowStatus.OpenedFromFileSystem.ToString() && saveAsInvoked)
                    {
                        references = this.openedReferences;
                    }

                    bool workflowCreated = this.uiHelper.CreateWorkflowInRegistry(this.newWorkflowName, references);
                    if (this.uiHelper.CurrentStatus == WorkflowStatus.OpenedFromFileSystem.ToString())
                    {
                        // This is used to check whether the worklfow was created from file system. 
                        // If it is not created then return with userRejected Save.
                        if (!workflowCreated)
                        {
                            this.usrRejectSave = true;
                            return;
                        }
                    }
                }
            }
            else
            {

                this.usrRejectSave = true;
                return;
            }

            // Workflow is saved into Registry.
            uiHelper.IsWFCommitted = true;

            lblStatus.Text = TridentResourceManager.GetString("SaveWorkflowSuccesfullySavedToRegistry");

            // refresh the workflow Tree.
            this.RefreshWorkFlowTree();


            // Refresh the activity tree. As new activities may be added on save of wf.
            this.RefreshActivityTree(false);


            this.EnableDisableSaveFileSystemMenu(false);
            this.EnableDisableSaveRegistryMenu(true);

            // after Saving Its Considered as open from the registry
            this.uiHelper.CurrentStatus = WorkflowStatus.OpenedFromRegistry.ToString();

            // Set the title of the window.
            this.Title = this.SetTitle();

            this.openedReferences.Clear();

            this.designerComposerControl.InitializeMachineCombo();
        }

        /// <summary>
        /// Checks if all the inputs of the passed model are valid.
        /// </summary>
        /// <param name="model">
        /// The model to check against.
        /// </param>
        /// <returns>
        /// True if all inputs are valid, false otherwise.
        /// </returns>
        private bool EnsureInputsValid(TridentWorkflowModel workflowModel, bool validateMetadata, bool showImportDialog)
        {
            bool inputsValid = true;
            bool isMetadataValid = true;
            bool areValuesValid = true;
            if (!this.saveAsInvoked)
            {
                // validate the workflow metadata.
                if (validateMetadata)
                {
                    isMetadataValid = this.ValidateWorkflowMetadata(workflowModel);
                }

                // if workflow meta data is valid only then validate the activity values.
                if (isMetadataValid)
                {
                    areValuesValid = !this.CheckPopupNecessity(workflowModel.Root);
                }
            }
            else
            {
                // If save as invoked then bring up the property dialog.
                areValuesValid = false;
                isMetadataValid = false;
            }

            if (isMetadataValid && areValuesValid)
            {
                return inputsValid;
            }
            else
            {
                if (showImportDialog)
                {
                    if (this.openedReferences != null)
                    {
                        ImportDialog dialog = new ImportDialog(this, this.registryConnection, ImportType.SaveToRegistry);
                        dialog.LoadFiles(this.openedReferences);
                        dialog.ShowDialog();

                        if (dialog.Canceled)
                        {
                            foreach (FileReference fileReference in this.openedReferences)
                            {
                                fileReference.UpdateExisting = false;
                                fileReference.AssemblyInRegistryToUpdate = null;
                            }
                            return false;
                        }

                        this.openedReferences = dialog.FileReferences;

                        // If the user has selected to update an existing workflow, set the workflow to update ID.
                        // This is needed for the workflow name validations.
                        FileReference workflowReference = this.openedReferences.FirstOrDefault(f => Helper.IsWorkflowFile(f.FilePath));
                        if (workflowReference.UpdateExisting)
                        {
                            workflowModel.WorkflowToUpdate = workflowReference.AssemblyInRegistryToUpdate.Id;
                        }
                    }
                    else
                    {
                        return false;
                    }
                }

                if (isMetadataValid && !areValuesValid)
                {
                    PropertyPanePopup propPanePopup = new PropertyPanePopup(this.registryConnection, workflowModel.Root, true);
                    propPanePopup.Owner = this;
                    propPanePopup.ShowDialog();
                    inputsValid = propPanePopup.ReadyToSave;
                }
                else
                {
                    PropertyPanePopup propPanePopup = new PropertyPanePopup(this.registryConnection,
                            workflowModel, true, this.saveAsInvoked);
                    propPanePopup.Owner = this;
                    propPanePopup.ShowDialog();
                    inputsValid = propPanePopup.ReadyToSave;
                }
            }

            return inputsValid;
        }

        /// <summary>
        /// Check if the user needs to be prompted for getting valid inputs.
        /// </summary>
        /// <param name="model">
        /// The model to check against.
        /// </param>
        /// <returns>
        /// True if popup needed, false otherwise.
        /// </returns>
        private bool CheckPopupNecessity(BaseModel model)
        {
            bool popupNeeded = false;
            if (model != null)
            {
                foreach (ParameterDescriptionModel paramModel in model.InputParameters)
                {
                    popupNeeded = BaseModel.CheckValueValidity(paramModel);
                    if (popupNeeded)
                    {
                        break;
                    }
                }

                if (!popupNeeded && (model.IsCompositeActivityModel || model.IsCompositeBlackBoxModel
                    || model.IsSubsectionModel))
                {
                    BaseCompositeModel compositeModel = model as BaseCompositeModel;
                    if (compositeModel != null)
                    {
                        foreach (BaseModel childModel in compositeModel.Children)
                        {
                            popupNeeded = this.CheckPopupNecessity(childModel);
                            if (popupNeeded)
                            {
                                break;
                            }
                        }
                    }
                }
            }

            return popupNeeded;
        }

        /// <summary>
        /// Validate the workflow name and the category.
        /// </summary>
        /// <returns>True to specify whether the metadata is valid. False otherwise.</returns>
        private bool ValidateWorkflowMetadata(TridentWorkflowModel workflow)
        {
            bool result = true;
            if (string.IsNullOrEmpty(workflow.Name))
            {
                result = false;
            }
            else if (workflow.Category == null || workflow.Category.Id.Equals(Guid.Empty))
            {
                result = false;
            }
            else
            {
                if (!TridentWorkflowModel.CheckNameForInvalidCharacters(workflow.Name))
                {
                    result = false;
                }
                else if (workflow.Id.Equals(Guid.Empty))
                {
                    result = CategoriesComposer.ValidateWorkflowName(workflow.Category.Id, workflow.Name, this.registryConnection);
                }
                else
                {
                    result = CategoriesComposer.ValidateWorkflowName(workflow.Category.Id, workflow.Id, workflow.Name, this.registryConnection);
                }
            }
            return result;
        }

        /// <summary>
        /// Saves the current wf to the file system
        /// </summary>
        private void SaveWorkflowToFileSystem()
        {
            // If the workflow has been deleted by external source, Dont save.
            if (uiHelper.CurrentStatus == WorkflowStatus.OpenedFromRegistry.ToString())
            {
                if (this.uiHelper.WorkflowComposer.CheckIfWorkflowDeleted(this.uiHelper.ComposerWorkflowModel.Id))
                {
                    // If the workflow has been deleted.
                    TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("DeletedWorkflowSave"));
                    this.DisableComposer();
                    this.RefreshWorkFlowTree();
                    return;
                }
            }

            if (!this.designerComposerControl.SaveConditionalActivities())
            {
                return;
            }

            if (this.EnsureInputsValid(this.uiHelper.ComposerWorkflowModel, false, false))
            {
                System.Windows.Forms.SaveFileDialog saveDialog = new System.Windows.Forms.SaveFileDialog();

                // Filters the XOML file in the current Directory.
                saveDialog.Filter = "Workflow Files (*.xoml)|*.xoml";

                // Make sure the dialog accepts only Filename supported by Win32.
                saveDialog.ValidateNames = true;

                // Restores the previous Directory the user had selected to Open/Save the file.
                saveDialog.RestoreDirectory = true;

                // Asks the User to create a new file if not present in the Directory.
                saveDialog.OverwritePrompt = true;

                string fileName = string.Empty;

                // Popup the save dialog untill users enter valid Name
                while (string.IsNullOrEmpty(fileName))
                {
                    try
                    {
                        System.Windows.Forms.DialogResult buttonClicked = saveDialog.ShowDialog();
                        if (buttonClicked == System.Windows.Forms.DialogResult.Cancel)
                        {
                            // Skip if user press cancel
                            return;
                        }

                        fileName = saveDialog.FileName;
                    }
                    catch (PathTooLongException exception)
                    {
                        saveDialog.FileName = string.Empty;
                        TridentMessageBox.ShowTridentErrorMessageBox(exception.Message);
                    }
                }

                // Open the File Dialog Box.
                if (!string.IsNullOrEmpty(fileName))
                {
                    try
                    {
                        // Save the workflow to Local File System.
                        if (uiHelper.SaveWorkflow(fileName))
                        {
                            // Save to file system
                            uiHelper.IsWFCommitted = true;

                            // Set the File Name
                            uiHelper.OpenedFileName = UIHelper.GetFileNameFromPath(fileName);

                            // Set the workflow name to the  ComposerWorkflowModel
                            uiHelper.ComposerWorkflowModel.Name = uiHelper.OpenedFileName;

                            lblStatus.Text = TridentResourceManager.GetString("SaveWorkflowSuccesfullySavedToFileSystem");
                            this.EnableDisableSaveFileSystemMenu(true);
                            this.EnableDisableSaveRegistryMenu(false);


                            // Clear the ComposerWorkflowModel Id - To avoid the same Model get updated if it again  Save-As to registry
                            uiHelper.ComposerWorkflowModel.ClearId();

                            // Reload the Saved workflow.
                            this.ClearConditionDataStore();
                            this.uiHelper.CurrentComposerControl.LoadWorkflow(uiHelper.ComposerWorkflowModel, true);

                            // If the workflows has been saved to File from the registry then the opened references will be empty. 
                            // So just add the created xoml as the reference. The user can add further references.
                            this.openedReferences.Remove(this.openedReferences.FirstOrDefault(o => Helper.IsWorkflowFile(o.FilePath)));

                            this.openedReferences.Insert(0, new FileReference(fileName, new Collection<string>()));


                            uiHelper.CurrentStatus = WorkflowStatus.OpenedFromFileSystem.ToString();

                            // Set the title of the window.
                            this.Title = this.SetTitle();
                        }
                        else
                        {
                            TridentMessageBox.ShowTridentErrorMessageBox(
                                this,
                                TridentResourceManager.GetString("SaveWorkflowFailedToSavedIntoFileSystem"));
                        }
                    }
                    catch (TridentCustomException exp)
                    {
                        TridentErrorHandler.HandleKnownExceptionsInUI(this, exp);
                    }
                }
            }
        }

        /// <summary>
        /// Prompts the user to save the Workflow 
        /// </summary>
        /// <returns> returns true if save Operation cancelled</returns>
        private bool SaveWorkFlowBeforeExecute()
        {
            bool executeWorkflow = true;
            MessageBoxResult saveResult;
            // Skip the check if Workflow is not opened from FileSystem and it was not commited
            if (uiHelper.IsWFCommitted && !uiHelper.CurrentStatus.Equals(WorkflowStatus.OpenedFromFileSystem.ToString())
                && !uiHelper.CurrentStatus.Equals(WorkflowStatus.NewWorkflow.ToString()))
            {
                if (!this.CheckPopupNecessity(this.uiHelper.ComposerWorkflowModel.Root))
                {
                    executeWorkflow = true;
                    return executeWorkflow;
                }
            }

            // Check if this is the latest version. Else set the saveasinvoked to true.
            string messageToShow = TridentResourceManager.GetString("SaveWorkflowOnExecuteMessage");
            bool invokeSaveAs = false;
            if (uiHelper.CurrentStatus.Equals(WorkflowStatus.OpenedFromRegistry.ToString()))
            {
                SR.Activity workflowToSave = SR.Activity.Load(this.uiHelper.CurrentWorkflowId, this.registryConnection);
                if (!workflowToSave.IsLatestVersion())
                {
                    messageToShow = TridentResourceManager.GetString("SaveOldWorkflowOnExecute");
                    invokeSaveAs = true;
                }
            }
            else if (uiHelper.CurrentStatus.Equals(WorkflowStatus.OpenedFromFileSystem.ToString()))
            {
                invokeSaveAs = true;
            }

            saveResult = TridentMessageBox.ShowTridentConfirmationYesNoMessageBox(messageToShow);
            if (MessageBoxResult.Yes == saveResult)
            {
                this.designerComposerControl.RemovePropertyPaneOnChange();
                try
                {
                    if (invokeSaveAs)
                    {
                        this.saveAsInvoked = true;
                    }

                    this.SaveWorkflowToRegistry();
                    if (this.usrRejectSave)
                    {
                        return executeWorkflow;
                    }
                    else
                    {
                        this.ClearConditionDataStore();

                        // Reload the saved Workflow
                        this.uiHelper.LoadWorkflowFromLeftPane(this.uiHelper.ComposerWorkflowModel.Id);

                        this.ChangeSaveButtonState(!this.designerComposerControl.CurrentWorkflowModel.NewerVersionsExist);

                        this.SetTitle();
                    }
                }
                catch (WorkflowValidationFailedException validationException)
                {
                    StringBuilder errorString = new StringBuilder();
                    foreach (System.Workflow.ComponentModel.Compiler.ValidationError error in validationException.Errors)
                    {
                        errorString.AppendLine(error.ErrorText);
                    }
                    executeWorkflow = false;
                    TridentMessageBox.ShowTridentErrorMessageBox(this, errorString.ToString());
                }
                catch (TridentCustomException ex)
                {
                    executeWorkflow = false;
                    this.usrRejectSave = false;
                    TridentErrorHandler.HandleTridentCustomExceptionInUI(this, ex);
                }
                catch (Exception exception)
                {
                    executeWorkflow = false;
                    this.usrRejectSave = false;
                    TridentErrorHandler.HandleKnownExceptionsInUI(this, exception, TridentResourceManager.GetString("SaveWorkflowFailedToSavedIntoRegistry"));
                }
                finally
                {
                    // Set saveasinvoked as false once the user saves it as a different workflow.
                    this.saveAsInvoked = false;
                }

                executeWorkflow = executeWorkflow ? executeWorkflow : this.usrRejectSave;
            }
            else if (MessageBoxResult.No == saveResult)
            {
                executeWorkflow = false;
            }
            else
            {
                executeWorkflow = false;
            }

            return executeWorkflow;
        }

        /// <summary>
        /// Save the changed workflow to the registry by opening the file save dialog.
        /// </summary>
        /// <returns>Cancel pressed.</returns>
        private bool SaveChangedWorkflow()
        {
            MessageBoxResult saveResult;

            bool isCancelled = false;

            if (this.uiHelper.CurrentStatus == WorkflowStatus.WorkflowClosed.ToString())
            {
                this.usrRejectSave = false;
                return false;
            }

            if (!uiHelper.IsWFCommitted)
            {
                bool invokeSaveAs = false;
                if (this.uiHelper.CurrentStatus.Equals(WorkflowStatus.OpenedFromRegistry.ToString()) || this.uiHelper.CurrentStatus.Equals(WorkflowStatus.NewWorkflow.ToString()))
                {
                    string messageToDisplay = TridentResourceManager.GetString("SaveWorkflowConfirmMessageForSaveToRegistry");
                    if (!this.uiHelper.CurrentWorkflowId.Equals(Guid.Empty))
                    {
                        try
                        {
                            SR.Activity workflowToSave = SR.Activity.Load(this.uiHelper.CurrentWorkflowId, this.registryConnection);
                            if (!workflowToSave.IsLatestVersion())
                            {
                                messageToDisplay = TridentResourceManager.GetString("SaveOldWorkflowOnClose");
                                invokeSaveAs = true;
                            }
                        }
                        catch (RecordNotFoundException ex)
                        {
                            TridentMessageBox.ShowTridentErrorMessageBox(TridentResourceManager.GetString("OpenedWorkflowDeleted"));
                            TridentErrorHandler.HandleUIException(ex);
                            this.DisableComposer();
                            return false;
                        }
                    }

                    // Request the user to save the Workflow into Registry.
                    saveResult = TridentMessageBox.ShowTridentConfirmationYesNoCancelMessageBox(messageToDisplay);
                }
                else
                {
                    // Request the user to save the Workflow into File system.
                    saveResult = TridentMessageBox.ShowTridentConfirmationYesNoCancelMessageBox(
                        TridentResourceManager.GetString("SaveWorkflowConfirmMessageForSaveToFilesystem"));
                }

                if (MessageBoxResult.Yes == saveResult)
                {
                    this.designerComposerControl.RemovePropertyPaneOnChange();
                    try
                    {
                        if (this.uiHelper.CurrentStatus.Equals(WorkflowStatus.OpenedFromRegistry.ToString()) || this.uiHelper.CurrentStatus.Equals(WorkflowStatus.NewWorkflow.ToString()))
                        {
                            if (invokeSaveAs)
                                this.saveAsInvoked = true;
                            this.SaveWorkflowToRegistry();
                        }
                        else
                        {
                            this.SaveWorkflowToFileSystem();
                        }
                    }
                    catch (WorkflowValidationFailedException validationException)
                    {
                        StringBuilder errorString = new StringBuilder();
                        foreach (System.Workflow.ComponentModel.Compiler.ValidationError error in validationException.Errors)
                        {
                            errorString.AppendLine(error.ErrorText);
                        }
                        isCancelled = true;
                        this.usrRejectSave = false;
                        TridentMessageBox.ShowTridentErrorMessageBox(this, errorString.ToString());
                    }
                    catch (TridentCustomException tridentCustomException)
                    {
                        isCancelled = true;
                        this.usrRejectSave = false;
                        if (tridentCustomException != null &&
                            tridentCustomException.ErrorNumber.Equals(TridentErrorConstants.ErrorNumber90000036.ToString(CultureInfo.CurrentCulture), StringComparison.CurrentCulture))
                        {
                            TridentMessageBox.ShowTridentErrorMessageBox(
                               this,
                               tridentCustomException.Message);
                        }
                        else
                        {
                            TridentMessageBox.ShowTridentErrorMessageBox(
                               this,
                               TridentResourceManager.GetString("SaveWorkflowFailedToSavedIntoRegistry"));
                        }
                    }
                    catch (Exception exception)
                    {
                        isCancelled = true;
                        this.usrRejectSave = false;
                        TridentErrorHandler.HandleKnownExceptionsInUI(this, exception, TridentResourceManager.GetString("SaveWorkflowFailedToSavedIntoRegistry"));
                    }
                    finally
                    {
                        // Set saveasinvoked as false once the user saves it as a different workflow.
                        this.saveAsInvoked = false;
                    }

                    if (!uiHelper.IsWFCommitted)
                    {
                        isCancelled = true;
                    }
                    else
                    {
                        isCancelled = false;
                    }
                }
                else if (MessageBoxResult.No == saveResult)
                {
                    isCancelled = false;
                    this.usrRejectSave = true;
                }
                else
                {
                    isCancelled = true;
                    this.usrRejectSave = false;
                }
            }
            else
            {
                isCancelled = false;
                this.usrRejectSave = false;
            }

            return isCancelled;
        }

        /// <summary>
        /// Set the title of the window,
        /// </summary>
        /// <returns>The title.</returns>
        private string SetTitle()
        {
            StringBuilder windowTitle = new StringBuilder();
            string workflowName = string.Empty;
            string windowName = string.Empty;

            try
            {
                windowName = TridentResourceManager.GetString("TitleForTrident");
                if (true == string.IsNullOrEmpty(windowName))
                {
                    windowName = ((Assembly.GetExecutingAssembly()).GetName()).Name;
                }
                if (this.uiHelper != null)
                {
                    if (this.uiHelper.ComposerWorkflowModel != null)
                    {
                        workflowName = this.uiHelper.ComposerWorkflowModel.GetDisplayName;
                    }

                    if (string.IsNullOrEmpty(workflowName) || string.IsNullOrEmpty(workflowName.Trim()))
                    {
                        windowTitle.Append(windowName);
                    }
                    else
                    {
                        windowTitle.Append(workflowName.Trim());
                        windowTitle.Append(" - ");
                        windowTitle.Append(windowName);
                    }
                }
                else
                {
                    windowTitle.Append(windowName);
                }
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleUIException(exception);
            }

            return windowTitle.ToString();
        }

        /// <summary>
        /// Set the Activity expander Header
        /// </summary>
        private void SetActivityExpanderHeader()
        {
            HeaderedContentControl header = new HeaderedContentControl();
            header.Content = TridentResourceManager.GetString("ActivityTreeHeader");
            header.HorizontalAlignment = HorizontalAlignment.Stretch;
            this.activityExpander.Tag = TridentResourceManager.GetString("TridentWindowTreeCollapseToolTip");
            this.activityExpander.Header = header;
        }

        /// <summary>
        /// Set the Workflow expander Header
        /// </summary>
        private void SetWorkflowExpanderHeader()
        {
            HeaderedContentControl header = new HeaderedContentControl();
            header.Content = TridentResourceManager.GetString("WorkflowsLeftPaneTitle");
            header.HorizontalAlignment = HorizontalAlignment.Stretch;
            this.workflowExpander.Tag = TridentResourceManager.GetString("TridentWindowTreeCollapseToolTip");
            this.workflowExpander.Header = header;
        }

        /// <summary>
        /// Disable the designer tab.
        /// </summary>
        private void DisableDesignerTab()
        {
            this.designerComposerControl.IsEnabled = false;
            this.designerComposerControl.Opacity = .3;
        }

        /// <summary>
        /// Enable the designer tab.
        /// </summary>
        private void EnableDesignerTab()
        {
            this.designerComposerControl.IsEnabled = true;
            this.designerComposerControl.Opacity = 1.0;
        }

        /// <summary>
        /// Shows the Monitor tab
        /// </summary>
        private void ShowMonitorTab()
        {
            this.ComposerTab.SelectedIndex = 1;
        }

        /// <summary>
        /// Shows the Composer tab
        /// </summary>
        private void ShowComposerTab()
        {
            this.ComposerTab.SelectedIndex = 0;
        }

        /// <summary>
        /// Disables the Composer window
        /// </summary>
        private void DisableComposer()
        {
            this.uiHelper.CloseWorkflow();
            this.uiHelper.ClearOpenFromFileSystemDetails();
            this.designerComposerControl.ResetTransforms();

            // Clear the Value of the Job Name.
            this.designerComposerControl.TxtJobName.ClearText();
            lblStatus.Text = string.Empty;

            this.ClearConditionDataStore();

            // Set the title of the window.
            this.Title = this.SetTitle();

            // Disable the designer tab.
            this.DisableDesignerTab();

            // Diable the Toggle button which is used to hide the Parameter bindings.
            this.tBtnHideParameterBindings.IsEnabled = false;
            this.designerComposerControl.InitializeMachineCombo();
        }

        /// <summary>
        /// Clears the data products in UI and from file system
        /// </summary>
        private void ClearDataProducts()
        {
            try
            {
                this.container.Resolve<IMonitorService>().ClearModel();
                this.container.Resolve<IDataProductService>().ClearModel();
            }
            catch (Exception ex)
            {
                TridentErrorHandler.HandleUIException(ex);
            }
        }

        /// <summary>
        /// Clear the data store.
        /// </summary>
        private void ClearConditionDataStore()
        {
            if (this.designerComposerControl != null && this.designerComposerControl.ConditionStore != null)
            {
                this.designerComposerControl.ConditionStore.ClearDataStore();
            }
        }

        /// <summary>
        /// Handler for teminate button click
        /// </summary>
        private void OnTerminateWorkflow(object sender, EventArgs e)
        {
            try
            {
                MessageBoxResult result = TridentMessageBox.ShowTridentConfirmationYesNoMessageBox(ScientificWorkFlow.ConfirmTerminateMessage);

                if (result == MessageBoxResult.Yes)
                {
                    this.terminatedByUser = true;
                    this.uiHelper.AbortCurrentJob(this.currentJobId);
                    //this.container.Resolve<IMonitorService>().Stop();
                }
            }
            catch (Exception ex)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(ex);
            }
        }

        /// <summary>
        /// Read the datatypes.
        /// </summary>
        private void ReadDatatypes()
        {
            DataTypesComposer.ReadAllDataTypes(this.dataTypes);
            UIHelper.ReadUserDataTypeXml(this.dataTypes);
        }

        /// <summary>
        /// Initialize the container.
        /// </summary>
        private void InitializeContainer()
        {
            this.container = new UnityContainer();
            this.container.RegisterInstance<IUnityContainer>(this.container, new ExternallyControlledLifetimeManager());
            this.container.RegisterInstance<IRegionManager>(this, new ExternallyControlledLifetimeManager());
            this.container.RegisterInstance<ComposerControl>("Monitor", this.MonitorComposerControl, new ExternallyControlledLifetimeManager());
            this.container.RegisterInstance<UIHelper>("UiHelper", this.uiHelper, new ExternallyControlledLifetimeManager());
        }

        /// <summary>
        /// Initialize the modules.
        /// </summary>
        private void InitializeModules()
        {
            try
            {
                this.module = this.container.Resolve<MonitorModule>();
                this.module.Initialize();
            }
            catch (Exception ex)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(ex);
            }
        }

        /// <summary>
        /// Initialize the mintor control.
        /// </summary>
        private void InitializeMonitorControl()
        {
            this.MonitorComposerControl = new ComposerControl(this.registryConnection,
                this.uiHelper.WorkflowComposer,
                this.dataTypes,
                RenderMode.MonitorMode);

            this.MonitorComposerControl.OnTerminate += new EventHandler(OnTerminateWorkflow);
            this.MonitorComposerControl.Name = "monitorComposerControl1";
            this.RegisterName(this.MonitorComposerControl.Name, this.MonitorComposerControl);
            this.MonitorRegion.Children.Add(this.MonitorComposerControl);
        }

        /// <summary>
        /// Loads the Subsection Meta data from the Registry
        /// </summary>
        private void InitializeSubSectionMetadata()
        {
            SR.Activity subsectionActivity = SR.Activity.CommonSearches.FindActivityInRegistry("TridentBasicActivities.Activities.SubSection", this.registryConnection);
            if (subsectionActivity != null)
            {
                ActivityMetadata subsectionMetadata = new ActivityMetadata(subsectionActivity);
                TridentModel.SubsectionMetadata.Data = subsectionMetadata;
            }
        }

        #endregion

        /// <summary>
        /// This method prompts the user for message when the workflow is running.  
        /// based on user input the return value will be decided.
        /// </summary>
        /// <returns>true if user clicks OK false otherwise</returns>
        public bool CanProceedOnJobExecution()
        {
            if (!this.IsWorkflowJobRunning)
            {
                return true;
            }
            else
            {
                MessageBoxResult result = TridentMessageBox.ShowTridentConfirmationOkCancelMessageBox(
                    ScientificWorkFlow.CanProceedOnJobExecutionMessage);
                if (result == MessageBoxResult.Cancel)
                {
                    return false;
                }

                this.currentJobId = Guid.Empty;
                return true;
            }
        }

        /// <summary>
        /// Gets the composer control for the designer.
        /// </summary>
        public ComposerControl DesignerComposerControl
        {
            get
            {
                return this.designerComposerControl;
            }
        }

        /// <summary>
        /// Gets or sets the monitor composer control.
        /// </summary>
        public ComposerControl MonitorComposerControl
        {
            get;
            private set;
        }

        #region IRegionManager Members

        public void Add(object view, string regionName)
        {
            Grid region = this.FindName(regionName) as Grid;
            if (region != null)
            {
                region.Children.Add(view as UIElement);
            }
        }

        /// <summary>
        /// Sets the title.
        /// </summary>
        /// <param name="title">The title.</param>
        public void SetTitle(string title)
        {
            if (!string.IsNullOrEmpty(title) && !string.IsNullOrEmpty(title.Trim()))
            {
                this.Title = title.Trim();
            }
        }

        #endregion

        /// <summary>
        /// Event handler for About Click
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">RoutedEventArgs</param>
        private void OnAboutClick(object sender, RoutedEventArgs e)
        {
            AboutBox aboutBox = new AboutBox();
            aboutBox.Owner = this;
            aboutBox.ShowDialog();
        }

        private void OnSaveAsPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.ShowMonitorTab();
            this.ShowComposerTab();
        }

        /// <summary>
        /// Event handler for Refreshing the Workflow tree
        /// </summary>
        /// <param name="sender">refresh button</param>
        /// <param name="e">RoutedEventArgs</param>
        private void OnWorkFlowTreeRefresh(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                if (!this.uiHelper.CurrentStatus.Equals(WorkflowStatus.WorkflowClosed.ToString()) && !uiHelper.IsWFCommitted)
                {
                    MessageBoxResult result = TridentMessageBox.ShowTridentConfirmationOkCancelMessageBox(ScientificWorkFlow.RefreshWorkflowWarning);
                    if (result == MessageBoxResult.Cancel)
                    {
                        Mouse.OverrideCursor = null;
                        return;
                    }
                }

                this.DisableComposer();
                this.RefreshWorkFlowTree();
            }

            catch (Exception ex)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(ex, ScientificWorkFlow.WorkflowRefreshException);
            }
            finally
            {
                Mouse.OverrideCursor = null;
            }
        }

        /// <summary>
        /// Event handler for refreshing the Activity tree
        /// </summary>
        /// <param name="sender">refresh button</param>
        /// <param name="e">RoutedEventArgs</param>
        private void OnActivityTreeRefresh(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.RefreshActivityTree(true);
            }
            finally
            {
                Mouse.OverrideCursor = null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnActivitiesLoaded(object sender, EventArgs e)
        {
            Panel.SetZIndex(this.interactiveBorder, -1);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnCategoryExpanding(object sender, EventArgs e)
        {
            Panel.SetZIndex(this.interactiveBorder, 1);
        }

        /// <summary>
        /// Event handler for Exit composer
        /// </summary>
        /// <param name="sender">Exit button</param>
        /// <param name="e">RoutedEventArgs</param>
        private void OnComposerExitClick(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Checks the save validity.
        /// </summary>
        /// <returns></returns>
        private bool CheckSaveValidity(out Collection<AssemblyInfoModel> multiAsmModels)
        {
            bool validSave = true;
            multiAsmModels = new Collection<AssemblyInfoModel>();
            if (this.uiHelper != null && this.uiHelper.ComposerWorkflowModel != null)
            {
                Collection<AssemblyInfoModel> assemblyModels = this.uiHelper.ComposerWorkflowModel.WorkflowAssociatedAssemblies;
                if (assemblyModels != null)
                {
                    var assemblyGroups = from model in assemblyModels
                                         group model by model.AssemblyFullName into assemblyGroup
                                         select new
                                         {
                                             AssemblyFullName = assemblyGroup.Key,
                                             ChecksumGroups = from model in assemblyGroup
                                                              group model by model.AssemblyChecksum into checksumGroup
                                                              select new
                                                              {
                                                                  Checksum = checksumGroup.Key,
                                                                  ChecksumGroup = checksumGroup
                                                              }
                                         };
					
					var multiAssemblyGroup = assemblyGroups.FirstOrDefault(assemblyGroup => assemblyGroup.ChecksumGroups.Count() > 1);
                    if (multiAssemblyGroup != null)
                    {
                        for (int index = 0; index < multiAssemblyGroup.ChecksumGroups.Count(); index++)
                        {
                            foreach (AssemblyInfoModel model in multiAssemblyGroup.ChecksumGroups.ElementAt(index).ChecksumGroup)
                            {
                                if (model.HolderModel.UpdateAvailable && !multiAsmModels.Contains(model))
                                {
                                    multiAsmModels.Add(model);
                                }
                            }
                        }

                        validSave = !(multiAsmModels.Count > 0);
                    }
                }
                else
                {
                    validSave = false;
                }

                if (validSave)
                {
                    IEnumerable<AssemblyInfoModel> activityAssemblies = assemblyModels.Where(a => a.IsActivityDll);
                    IEnumerable<IGrouping<string, AssemblyInfoModel>> identicalAssemblyGroups = activityAssemblies.GroupBy(a => a.AssemblyFullName);
                    foreach (IGrouping<string, AssemblyInfoModel> identicalAssemblies in identicalAssemblyGroups)
                    {
                        BaseModel baseActivityModel = null;
                        foreach (AssemblyInfoModel assemblyInfo in identicalAssemblies)
                        {
                            if (baseActivityModel == null)
                            {
                                baseActivityModel = assemblyInfo.HolderModel;
                                continue;
                            }

                            if (assemblyInfo.HolderModel.AssociatedAssemblies.Union(
                                baseActivityModel.AssociatedAssemblies,
                                new AssemblyInfoComparer()).Count() != baseActivityModel.AssociatedAssemblies.Count)
                            {
                                validSave = false;
                                multiAsmModels.Add(assemblyInfo);
                                break;
                            }
                        }

                        if (!validSave)
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                validSave = false;
            }

            return validSave;
        }

        #region IDisposable Members

        /// <summary>
        /// Disposes members that implement IDisposable.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // The bulk of the clean-up code is implemented in Dispose(bool)
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.activityTree != null)
                {
                    this.activityTree.Dispose();
                }

                if (this.container != null)
                {
                    this.container.Dispose();
                }
            }
        }

        #endregion
    }
}